├── .gitignore ├── .swift-version ├── LICENSE ├── README-Chinese.md ├── README.md ├── ScreenShots ├── page1.jpg ├── page10.jpg ├── page11.jpg ├── page2.jpg ├── page3.jpg ├── page4.jpg ├── page5.jpg ├── page6.jpg ├── page7.jpg ├── page8.jpg └── page9.jpg ├── Source ├── LBXPermissions.swift ├── LBXScanLineAnimation.swift ├── LBXScanNetAnimation.swift ├── LBXScanView.swift ├── LBXScanViewController.swift ├── LBXScanViewStyle.swift └── LBXScanWrapper.swift ├── SwiftScanner ├── Info.plist └── SwiftScanner.h ├── swiftScan.podspec ├── swiftScan.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── SwiftScanner.xcscheme └── swiftScan ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── CodeScan.bundle ├── device_scan@2x.png ├── qrcode_Scan_weixin_Line@2x.png ├── qrcode_scan_btn_flash_down@2x.png ├── qrcode_scan_btn_flash_nor@2x.png ├── qrcode_scan_btn_myqrcode_down@2x.png ├── qrcode_scan_btn_myqrcode_nor@2x.png ├── qrcode_scan_btn_photo_down@2x.png ├── qrcode_scan_btn_photo_nor@2x.png ├── qrcode_scan_btn_scan_off@2x.png ├── qrcode_scan_full_net.png ├── qrcode_scan_light_green@2x.png ├── qrcode_scan_part_net.png ├── qrcode_scan_titlebar_back_nor@2x.png └── qrcode_scan_titlebar_back_pressed@2x.png ├── Info.plist ├── MainTableViewController.swift ├── MyCodeViewController.swift ├── QQScanViewController.swift ├── ScanResultController.swift ├── ScanResultController.xib ├── ViewController.swift ├── logo.JPG └── zh-Hans.lproj ├── LaunchScreen.strings └── Main.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | swiftScan/.DS_Store 35 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README-Chinese.md: -------------------------------------------------------------------------------- 1 | 2 | # iOS 二维码、条形码 Swift 版本 3 | 4 | 5 | ### Objective-c版本: **[LBXScan](https://github.com/MxABC/LBXScan)** 6 | 7 | 8 | 9 | ## 介绍 10 | **swift封装系统自带扫码及识别图片功能** 11 | - 扫码界面效果封装 12 | - 二维码和条形码识别及生成 13 | - 相册获取图片后识别(测试效果不好...) 14 | 15 | **模仿其他app** 16 | - 模仿QQ扫码界面 17 | - 支付宝扫码框效果 18 | - 微信扫码框效果 19 | 20 | **其他设置参数自定义效果** 21 | 22 | - 扫码框周围区域背景色可设置 23 | - 扫码框颜色可也设置 24 | - 扫码框4个角的颜色可设置、大小可设置 25 | - 可设置只识别扫码框内的图像区域 26 | - 可设置扫码成功后,获取当前图片 27 | - 根据扫码结果,截取码的部分图像(在模仿qq扫码界面,扫码成功后可看到) 28 | - 动画效果选择: 线条上下移动、网格形式移动、中间线条不移动(一般扫码条形码的效果). 29 | 30 | 31 | 32 | 33 | ### CocoaPods安装 34 | 35 | 36 | 37 | ```ruby 38 | source 'https://github.com/CocoaPods/Specs.git' 39 | platform :ios, '8.0' 40 | use_frameworks! 41 | pod 'swiftScan', '~> 1.1.2' 42 | ``` 43 | 44 | 45 | ### 手动安装 46 | 下载后将Source文件夹copy到工程即可 47 | 48 | 49 | ### 版本 50 | #### v1.0.9 51 | swift3.0 52 | #### v1.0.8 53 | 修改适应cocoapods安装后,编译报错bug 54 | 55 | 56 | ## 界面效果 57 | 58 | (加载速度慢,可刷新网页) 59 | 60 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page1.jpg) 61 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page2.jpg) 62 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page3.jpg) 63 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page4.jpg) 64 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page5.jpg) 65 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page6.jpg) 66 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page7.jpg) 67 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page8.jpg) 68 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page9.jpg) 69 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page10.jpg) 70 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page11.jpg) 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # iOS qrCode、barCode Swift Version 3 | 4 | [![Platform](https://img.shields.io/badge/platform-iOS-red.svg)](https://developer.apple.com/iphone/index.action) 5 | [![Language](http://img.shields.io/badge/language-swift4.0-yellow.svg?style=flat 6 | )](https://en.wikipedia.org/wiki/swift) 7 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://mit-license.org) 8 | 9 | 10 | 11 | ### Objective-c Version: **[LBXScan](https://github.com/MxABC/LBXScan)** 12 | 13 | ### [中文介绍](https://github.com/MxABC/swiftScan/blob/master/README-Chinese.md) 14 | 15 | 16 | ## Introduce 17 | #### Swift: The packaging system API comes with scan code and image recognition function 18 | 19 | - scan code interface 20 | - QR code and bar code recognition and generation 21 | - image recognition from the Album (Test results are not good) 22 | 23 | #### **Imitate other app** 24 | 25 | 1、 QQ scan code interface 26 | 2、Alipay scan code interface 27 | 3、Wechat scan code interface 28 | 29 | #### **Other settings parameters custom effects** 30 | - The background color can be set around the scan frame 31 | - Scan code frame color can also be set 32 | - Scan code box 4 corners of the color can be set, the size can be set 33 | - Can only be set to identify the scan code box in the image area 34 | - Scan code can be set to get the current picture 35 | - According to the results of the scan code, can intercept part of the image 36 | - Animation options: Line up and down、Grid form movement、Middle line not moving(use for bar code scanning commonly) 37 | 38 | 39 | 40 | ### Installation with CocoaPods 41 | 42 | 43 | 44 | ```ruby 45 | platform :ios, '8.0' 46 | use_frameworks! 47 | pod 'swiftScan', :git => 'https://github.com/MxABC/swiftScan.git' 48 | ``` 49 | 50 | 51 | ### manually 52 | download and copy the Source folder to your project 53 | 54 | 55 | 56 | ## View effect 57 | 58 | 59 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page1.jpg) 60 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page2.jpg) 61 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page3.jpg) 62 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page4.jpg) 63 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page5.jpg) 64 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page6.jpg) 65 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page7.jpg) 66 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page8.jpg) 67 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page9.jpg) 68 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page10.jpg) 69 | ![image](https://github.com/MxABC/swiftScan/blob/master/ScreenShots/page11.jpg) 70 | -------------------------------------------------------------------------------- /ScreenShots/page1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page1.jpg -------------------------------------------------------------------------------- /ScreenShots/page10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page10.jpg -------------------------------------------------------------------------------- /ScreenShots/page11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page11.jpg -------------------------------------------------------------------------------- /ScreenShots/page2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page2.jpg -------------------------------------------------------------------------------- /ScreenShots/page3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page3.jpg -------------------------------------------------------------------------------- /ScreenShots/page4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page4.jpg -------------------------------------------------------------------------------- /ScreenShots/page5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page5.jpg -------------------------------------------------------------------------------- /ScreenShots/page6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page6.jpg -------------------------------------------------------------------------------- /ScreenShots/page7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page7.jpg -------------------------------------------------------------------------------- /ScreenShots/page8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page8.jpg -------------------------------------------------------------------------------- /ScreenShots/page9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/ScreenShots/page9.jpg -------------------------------------------------------------------------------- /Source/LBXPermissions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXPermissions.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/15. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AVFoundation 11 | import Photos 12 | import AssetsLibrary 13 | 14 | 15 | 16 | class LBXPermissions: NSObject { 17 | 18 | //MARK: ----获取相册权限 19 | static func authorizePhotoWith(comletion: @escaping (Bool) -> Void) { 20 | let granted = PHPhotoLibrary.authorizationStatus() 21 | switch granted { 22 | case PHAuthorizationStatus.authorized: 23 | comletion(true) 24 | case PHAuthorizationStatus.denied, PHAuthorizationStatus.restricted: 25 | comletion(false) 26 | case PHAuthorizationStatus.notDetermined: 27 | PHPhotoLibrary.requestAuthorization({ status in 28 | DispatchQueue.main.async { 29 | comletion(status == PHAuthorizationStatus.authorized) 30 | } 31 | }) 32 | case .limited: 33 | comletion(true) 34 | @unknown default: 35 | comletion(false) 36 | } 37 | } 38 | 39 | //MARK: ---相机权限 40 | static func authorizeCameraWith(completion: @escaping (Bool) -> Void) { 41 | let granted = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) 42 | switch granted { 43 | case .authorized: 44 | completion(true) 45 | case .denied: 46 | completion(false) 47 | case .restricted: 48 | completion(false) 49 | case .notDetermined: 50 | AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) in 51 | DispatchQueue.main.async { 52 | completion(granted) 53 | } 54 | }) 55 | @unknown default: 56 | completion(false) 57 | } 58 | } 59 | 60 | //MARK: 跳转到APP系统设置权限界面 61 | static func jumpToSystemPrivacySetting() { 62 | guard let appSetting = URL(string: UIApplication.openSettingsURLString) else { 63 | return 64 | } 65 | if #available(iOS 10, *) { 66 | UIApplication.shared.open(appSetting, options: [:], completionHandler: nil) 67 | } else { 68 | UIApplication.shared.openURL(appSetting) 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Source/LBXScanLineAnimation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanLineAnimation.swift 3 | // swiftScan 4 | // 5 | // Created by lbxia on 15/12/9. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LBXScanLineAnimation: UIImageView { 12 | 13 | var isAnimationing = false 14 | var animationRect = CGRect.zero 15 | 16 | func startAnimatingWithRect(animationRect: CGRect, parentView: UIView, image: UIImage?) { 17 | self.image = image 18 | self.animationRect = animationRect 19 | parentView.addSubview(self) 20 | 21 | isHidden = false 22 | isAnimationing = true 23 | if image != nil { 24 | stepAnimation() 25 | } 26 | } 27 | 28 | @objc func stepAnimation() { 29 | guard isAnimationing else { 30 | return 31 | } 32 | var frame = animationRect 33 | let hImg = image!.size.height * animationRect.size.width / image!.size.width 34 | 35 | frame.origin.y -= hImg 36 | frame.size.height = hImg 37 | self.frame = frame 38 | alpha = 0.0 39 | 40 | UIView.animate(withDuration: 1.4, animations: { 41 | self.alpha = 1.0 42 | var frame = self.animationRect 43 | let hImg = self.image!.size.height * self.animationRect.size.width / self.image!.size.width 44 | frame.origin.y += (frame.size.height - hImg) 45 | frame.size.height = hImg 46 | self.frame = frame 47 | }, completion: { _ in 48 | self.perform(#selector(LBXScanLineAnimation.stepAnimation), with: nil, afterDelay: 0.3) 49 | }) 50 | } 51 | 52 | func stopStepAnimating() { 53 | isHidden = true 54 | isAnimationing = false 55 | } 56 | 57 | public static func instance() -> LBXScanLineAnimation { 58 | return LBXScanLineAnimation() 59 | } 60 | 61 | deinit { 62 | stopStepAnimating() 63 | } 64 | 65 | } 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Source/LBXScanNetAnimation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanNetAnimation.swift 3 | // swiftScan 4 | // 5 | // Created by lbxia on 15/12/9. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LBXScanNetAnimation: UIImageView { 12 | 13 | var isAnimationing = false 14 | var animationRect = CGRect.zero 15 | 16 | public static func instance() -> LBXScanNetAnimation { 17 | return LBXScanNetAnimation() 18 | } 19 | 20 | func startAnimatingWithRect(animationRect: CGRect, parentView: UIView, image: UIImage?) { 21 | self.image = image 22 | self.animationRect = animationRect 23 | parentView.addSubview(self) 24 | 25 | isHidden = false 26 | 27 | isAnimationing = true 28 | 29 | if image != nil { 30 | stepAnimation() 31 | } 32 | } 33 | 34 | @objc func stepAnimation() { 35 | guard isAnimationing else { 36 | return 37 | } 38 | var frame = animationRect 39 | 40 | let hImg = image!.size.height * animationRect.size.width / image!.size.width 41 | 42 | frame.origin.y -= hImg 43 | frame.size.height = hImg 44 | self.frame = frame 45 | 46 | alpha = 0.0 47 | 48 | UIView.animate(withDuration: 1.2, animations: { 49 | self.alpha = 1.0 50 | 51 | var frame = self.animationRect 52 | let hImg = self.image!.size.height * self.animationRect.size.width / self.image!.size.width 53 | 54 | frame.origin.y += (frame.size.height - hImg) 55 | frame.size.height = hImg 56 | 57 | self.frame = frame 58 | 59 | }, completion: { _ in 60 | self.perform(#selector(LBXScanNetAnimation.stepAnimation), with: nil, afterDelay: 0.3) 61 | }) 62 | } 63 | 64 | func stopStepAnimating() { 65 | isHidden = true 66 | isAnimationing = false 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Source/LBXScanView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanView.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/8. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class LBXScanView: UIView { 12 | 13 | // 扫码区域各种参数 14 | var viewStyle = LBXScanViewStyle() 15 | 16 | // 扫码区域 17 | var scanRetangleRect = CGRect.zero 18 | 19 | // 线条扫码动画封装 20 | var scanLineAnimation: LBXScanLineAnimation? 21 | 22 | // 网格扫码动画封装 23 | var scanNetAnimation: LBXScanNetAnimation? 24 | 25 | // 线条在中间位置,不移动 26 | var scanLineStill: UIImageView? 27 | 28 | // 启动相机时 菊花等待 29 | var activityView: UIActivityIndicatorView? 30 | 31 | // 启动相机中的提示文字 32 | var labelReadying: UILabel? 33 | 34 | // 记录动画状态 35 | var isAnimationing = false 36 | 37 | /** 38 | 初始化扫描界面 39 | - parameter frame: 界面大小,一般为视频显示区域 40 | - parameter vstyle: 界面效果参数 41 | 42 | - returns: instancetype 43 | */ 44 | public init(frame: CGRect, vstyle: LBXScanViewStyle) { 45 | viewStyle = vstyle 46 | 47 | switch viewStyle.anmiationStyle { 48 | case LBXScanViewAnimationStyle.LineMove: 49 | scanLineAnimation = LBXScanLineAnimation.instance() 50 | case LBXScanViewAnimationStyle.NetGrid: 51 | scanNetAnimation = LBXScanNetAnimation.instance() 52 | case LBXScanViewAnimationStyle.LineStill: 53 | scanLineStill = UIImageView() 54 | scanLineStill?.image = viewStyle.animationImage 55 | default: 56 | break 57 | } 58 | 59 | var frameTmp = frame 60 | frameTmp.origin = CGPoint.zero 61 | 62 | super.init(frame: frameTmp) 63 | 64 | backgroundColor = UIColor.clear 65 | } 66 | 67 | override init(frame: CGRect) { 68 | var frameTmp = frame 69 | frameTmp.origin = CGPoint.zero 70 | 71 | super.init(frame: frameTmp) 72 | 73 | backgroundColor = UIColor.clear 74 | } 75 | 76 | public required init?(coder aDecoder: NSCoder) { 77 | self.init() 78 | } 79 | 80 | deinit { 81 | if scanLineAnimation != nil { 82 | scanLineAnimation!.stopStepAnimating() 83 | } 84 | if scanNetAnimation != nil { 85 | scanNetAnimation!.stopStepAnimating() 86 | } 87 | } 88 | 89 | 90 | // 开始扫描动画 91 | func startScanAnimation() { 92 | guard !isAnimationing else { 93 | return 94 | } 95 | isAnimationing = true 96 | 97 | let cropRect = getScanRectForAnimation() 98 | 99 | switch viewStyle.anmiationStyle { 100 | case .LineMove: 101 | scanLineAnimation?.startAnimatingWithRect(animationRect: cropRect, 102 | parentView: self, 103 | image: viewStyle.animationImage) 104 | case .NetGrid: 105 | scanNetAnimation?.startAnimatingWithRect(animationRect: cropRect, 106 | parentView: self, 107 | image: viewStyle.animationImage) 108 | case .LineStill: 109 | let stillRect = CGRect(x: cropRect.origin.x + 20, 110 | y: cropRect.origin.y + cropRect.size.height / 2, 111 | width: cropRect.size.width - 40, 112 | height: 2) 113 | scanLineStill?.frame = stillRect 114 | 115 | addSubview(scanLineStill!) 116 | scanLineStill?.isHidden = false 117 | default: break 118 | } 119 | } 120 | 121 | // 开始扫描动画 122 | func stopScanAnimation() { 123 | isAnimationing = false 124 | switch viewStyle.anmiationStyle { 125 | case .LineMove: 126 | scanLineAnimation?.stopStepAnimating() 127 | case .NetGrid: 128 | scanNetAnimation?.stopStepAnimating() 129 | case .LineStill: 130 | scanLineStill?.isHidden = true 131 | default: break 132 | } 133 | } 134 | 135 | // Only override drawRect: if you perform custom drawing. 136 | // An empty implementation adversely affects performance during animation. 137 | open override func draw(_ rect: CGRect) { 138 | drawScanRect() 139 | } 140 | 141 | //MARK: ----- 绘制扫码效果----- 142 | func drawScanRect() { 143 | let XRetangleLeft = viewStyle.xScanRetangleOffset 144 | var sizeRetangle = CGSize(width: frame.size.width - XRetangleLeft * 2.0, height: frame.size.width - XRetangleLeft * 2.0) 145 | 146 | if viewStyle.whRatio != 1.0 { 147 | let w = sizeRetangle.width 148 | var h = w / viewStyle.whRatio 149 | h = CGFloat(Int(h)) 150 | sizeRetangle = CGSize(width: w, height: h) 151 | } 152 | 153 | // 扫码区域Y轴最小坐标 154 | let YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height / 2.0 - viewStyle.centerUpOffset 155 | let YMaxRetangle = YMinRetangle + sizeRetangle.height 156 | let XRetangleRight = frame.size.width - XRetangleLeft 157 | 158 | guard let context = UIGraphicsGetCurrentContext() else { 159 | return 160 | } 161 | 162 | // 非扫码区域半透明 163 | // 设置非识别区域颜色 164 | context.setFillColor(viewStyle.color_NotRecoginitonArea.cgColor) 165 | // 填充矩形 166 | // 扫码区域上面填充 167 | var rect = CGRect(x: 0, y: 0, width: frame.size.width, height: YMinRetangle) 168 | context.fill(rect) 169 | 170 | // 扫码区域左边填充 171 | rect = CGRect(x: 0, y: YMinRetangle, width: XRetangleLeft, height: sizeRetangle.height) 172 | context.fill(rect) 173 | 174 | // 扫码区域右边填充 175 | rect = CGRect(x: XRetangleRight, y: YMinRetangle, width: XRetangleLeft, height: sizeRetangle.height) 176 | context.fill(rect) 177 | 178 | // 扫码区域下面填充 179 | rect = CGRect(x: 0, y: YMaxRetangle, width: frame.size.width, height: frame.size.height - YMaxRetangle) 180 | context.fill(rect) 181 | // 执行绘画 182 | context.strokePath() 183 | 184 | if viewStyle.isNeedShowRetangle { 185 | // 中间画矩形(正方形) 186 | context.setStrokeColor(viewStyle.colorRetangleLine.cgColor) 187 | context.setLineWidth(viewStyle.widthRetangleLine) 188 | context.addRect(CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height)) 189 | 190 | // CGContextMoveToPoint(context, XRetangleLeft, YMinRetangle); 191 | // CGContextAddLineToPoint(context, XRetangleLeft+sizeRetangle.width, YMinRetangle); 192 | 193 | context.strokePath() 194 | } 195 | 196 | scanRetangleRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height) 197 | 198 | 199 | // 画矩形框4格外围相框角 200 | 201 | // 相框角的宽度和高度 202 | let wAngle = viewStyle.photoframeAngleW 203 | let hAngle = viewStyle.photoframeAngleH 204 | 205 | // 4个角的 线的宽度 206 | let linewidthAngle = viewStyle.photoframeLineW // 经验参数:6和4 207 | 208 | // 画扫码矩形以及周边半透明黑色坐标参数 209 | var diffAngle = linewidthAngle / 3 210 | diffAngle = linewidthAngle / 2 // 框外面4个角,与框有缝隙 211 | diffAngle = linewidthAngle / 2 // 框4个角 在线上加4个角效果 212 | diffAngle = 0 // 与矩形框重合 213 | 214 | switch viewStyle.photoframeAngleStyle { 215 | case .Outer: diffAngle = linewidthAngle / 3 // 框外面4个角,与框紧密联系在一起 216 | case .On: diffAngle = 0 217 | case .Inner: diffAngle = -viewStyle.photoframeLineW / 2 218 | } 219 | 220 | context.setStrokeColor(viewStyle.colorAngle.cgColor) 221 | context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 222 | 223 | // Draw them with a 2.0 stroke width so they are a bit more visible. 224 | context.setLineWidth(linewidthAngle) 225 | 226 | 227 | // 228 | let leftX = XRetangleLeft - diffAngle 229 | let topY = YMinRetangle - diffAngle 230 | let rightX = XRetangleRight + diffAngle 231 | let bottomY = YMaxRetangle + diffAngle 232 | 233 | // 左上角水平线 234 | context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: topY)) 235 | context.addLine(to: CGPoint(x: leftX + wAngle, y: topY)) 236 | 237 | // 左上角垂直线 238 | context.move(to: CGPoint(x: leftX, y: topY - linewidthAngle / 2)) 239 | context.addLine(to: CGPoint(x: leftX, y: topY + hAngle)) 240 | 241 | // 左下角水平线 242 | context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: bottomY)) 243 | context.addLine(to: CGPoint(x: leftX + wAngle, y: bottomY)) 244 | 245 | // 左下角垂直线 246 | context.move(to: CGPoint(x: leftX, y: bottomY + linewidthAngle / 2)) 247 | context.addLine(to: CGPoint(x: leftX, y: bottomY - hAngle)) 248 | 249 | // 右上角水平线 250 | context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: topY)) 251 | context.addLine(to: CGPoint(x: rightX - wAngle, y: topY)) 252 | 253 | // 右上角垂直线 254 | context.move(to: CGPoint(x: rightX, y: topY - linewidthAngle / 2)) 255 | context.addLine(to: CGPoint(x: rightX, y: topY + hAngle)) 256 | 257 | // 右下角水平线 258 | context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: bottomY)) 259 | context.addLine(to: CGPoint(x: rightX - wAngle, y: bottomY)) 260 | 261 | // 右下角垂直线 262 | context.move(to: CGPoint(x: rightX, y: bottomY + linewidthAngle / 2)) 263 | context.addLine(to: CGPoint(x: rightX, y: bottomY - hAngle)) 264 | 265 | context.strokePath() 266 | } 267 | 268 | // 根据矩形区域,获取识别区域 269 | static func getScanRectWithPreView(preView: UIView, style: LBXScanViewStyle) -> CGRect { 270 | let XRetangleLeft = style.xScanRetangleOffset 271 | let width = preView.frame.size.width - XRetangleLeft * 2 272 | let height = width 273 | var sizeRetangle = CGSize(width: width, height: height) 274 | 275 | if style.whRatio != 1 { 276 | let w = sizeRetangle.width 277 | var h = w / style.whRatio 278 | 279 | let hInt: Int = Int(h) 280 | h = CGFloat(hInt) 281 | 282 | sizeRetangle = CGSize(width: w, height: h) 283 | } 284 | 285 | // 扫码区域Y轴最小坐标 286 | let YMinRetangle = preView.frame.size.height / 2.0 - sizeRetangle.height / 2.0 - style.centerUpOffset 287 | // 扫码区域坐标 288 | let cropRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height) 289 | 290 | // 计算兴趣区域 291 | var rectOfInterest: CGRect 292 | 293 | // ref:http://www.cocoachina.com/ios/20141225/10763.html 294 | let size = preView.bounds.size 295 | let p1 = size.height / size.width 296 | 297 | let p2: CGFloat = 1920.0 / 1080.0 // 使用了1080p的图像输出 298 | if p1 < p2 { 299 | let fixHeight = size.width * 1920.0 / 1080.0 300 | let fixPadding = (fixHeight - size.height) / 2 301 | rectOfInterest = CGRect(x: (cropRect.origin.y + fixPadding) / fixHeight, 302 | y: cropRect.origin.x / size.width, 303 | width: cropRect.size.height / fixHeight, 304 | height: cropRect.size.width / size.width) 305 | 306 | } else { 307 | let fixWidth = size.height * 1080.0 / 1920.0 308 | let fixPadding = (fixWidth - size.width) / 2 309 | rectOfInterest = CGRect(x: cropRect.origin.y / size.height, 310 | y: (cropRect.origin.x + fixPadding) / fixWidth, 311 | width: cropRect.size.height / size.height, 312 | height: cropRect.size.width / fixWidth) 313 | } 314 | 315 | return rectOfInterest 316 | } 317 | 318 | func getRetangeSize() -> CGSize { 319 | let XRetangleLeft = viewStyle.xScanRetangleOffset 320 | var sizeRetangle = CGSize(width: frame.size.width - XRetangleLeft * 2, height: frame.size.width - XRetangleLeft * 2) 321 | 322 | let w = sizeRetangle.width 323 | var h = w / viewStyle.whRatio 324 | h = CGFloat(Int(h)) 325 | sizeRetangle = CGSize(width: w, height: h) 326 | 327 | return sizeRetangle 328 | } 329 | 330 | func deviceStartReadying(readyStr: String) { 331 | let XRetangleLeft = viewStyle.xScanRetangleOffset 332 | let sizeRetangle = getRetangeSize() 333 | 334 | // 扫码区域Y轴最小坐标 335 | let YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height / 2.0 - viewStyle.centerUpOffset 336 | 337 | // 设备启动状态提示 338 | if activityView == nil { 339 | activityView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) 340 | 341 | activityView?.center = CGPoint(x: XRetangleLeft + sizeRetangle.width / 2 - 50, y: YMinRetangle + sizeRetangle.height / 2) 342 | activityView?.style = UIActivityIndicatorView.Style.whiteLarge 343 | 344 | addSubview(activityView!) 345 | 346 | let labelReadyRect = CGRect(x: activityView!.frame.origin.x + activityView!.frame.size.width + 10, 347 | y: activityView!.frame.origin.y, 348 | width: 100, 349 | height: 30) 350 | labelReadying = UILabel(frame: labelReadyRect) 351 | labelReadying?.text = readyStr 352 | labelReadying?.backgroundColor = UIColor.clear 353 | labelReadying?.textColor = UIColor.white 354 | labelReadying?.font = UIFont.systemFont(ofSize: 18.0) 355 | addSubview(labelReadying!) 356 | } 357 | 358 | addSubview(labelReadying!) 359 | activityView?.startAnimating() 360 | } 361 | 362 | func deviceStopReadying() { 363 | if activityView != nil { 364 | activityView?.stopAnimating() 365 | activityView?.removeFromSuperview() 366 | labelReadying?.removeFromSuperview() 367 | 368 | activityView = nil 369 | labelReadying = nil 370 | } 371 | } 372 | 373 | } 374 | 375 | //MARK: - 公开方法 376 | public extension LBXScanView { 377 | 378 | /// 获取扫描动画的Rect 379 | func getScanRectForAnimation() -> CGRect { 380 | let XRetangleLeft = viewStyle.xScanRetangleOffset 381 | var sizeRetangle = CGSize(width: frame.size.width - XRetangleLeft * 2, 382 | height: frame.size.width - XRetangleLeft * 2) 383 | 384 | if viewStyle.whRatio != 1 { 385 | let w = sizeRetangle.width 386 | let h = w / viewStyle.whRatio 387 | sizeRetangle = CGSize(width: w, height: CGFloat(Int(h))) 388 | } 389 | 390 | // 扫码区域Y轴最小坐标 391 | let YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height / 2.0 - viewStyle.centerUpOffset 392 | // 扫码区域坐标 393 | let cropRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height) 394 | 395 | return cropRect 396 | } 397 | 398 | } 399 | -------------------------------------------------------------------------------- /Source/LBXScanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanViewController.swift 3 | // swiftScan 4 | // 5 | // Created by lbxia on 15/12/8. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | import AVFoundation 12 | 13 | public protocol LBXScanViewControllerDelegate: class { 14 | func scanFinished(scanResult: LBXScanResult, error: String?) 15 | } 16 | 17 | public protocol QRRectDelegate { 18 | func drawwed() 19 | } 20 | 21 | open class LBXScanViewController: UIViewController { 22 | 23 | // 返回扫码结果,也可以通过继承本控制器,改写该handleCodeResult方法即可 24 | open weak var scanResultDelegate: LBXScanViewControllerDelegate? 25 | 26 | open var delegate: QRRectDelegate? 27 | 28 | open var scanObj: LBXScanWrapper? 29 | 30 | open var scanStyle: LBXScanViewStyle? = LBXScanViewStyle() 31 | 32 | open var qRScanView: LBXScanView? 33 | 34 | // 启动区域识别功能 35 | open var isOpenInterestRect = false 36 | 37 | //连续扫码 38 | open var isSupportContinuous = false; 39 | 40 | // 识别码的类型 41 | public var arrayCodeType: [AVMetadataObject.ObjectType]? 42 | 43 | // 是否需要识别后的当前图像 44 | public var isNeedCodeImage = false 45 | 46 | // 相机启动提示文字 47 | public var readyString: String! = "loading" 48 | 49 | open override func viewDidLoad() { 50 | super.viewDidLoad() 51 | 52 | // Do any additional setup after loading the view. 53 | 54 | // [self.view addSubview:_qRScanView]; 55 | view.backgroundColor = UIColor.black 56 | edgesForExtendedLayout = UIRectEdge(rawValue: 0) 57 | } 58 | 59 | open func setNeedCodeImage(needCodeImg: Bool) { 60 | isNeedCodeImage = needCodeImg 61 | } 62 | 63 | // 设置框内识别 64 | open func setOpenInterestRect(isOpen: Bool) { 65 | isOpenInterestRect = isOpen 66 | } 67 | 68 | open override func viewDidAppear(_ animated: Bool) { 69 | super.viewDidAppear(animated) 70 | drawScanView() 71 | perform(#selector(LBXScanViewController.startScan), with: nil, afterDelay: 0.3) 72 | } 73 | 74 | @objc open func startScan() { 75 | if scanObj == nil { 76 | var cropRect = CGRect.zero 77 | if isOpenInterestRect { 78 | cropRect = LBXScanView.getScanRectWithPreView(preView: view, style: scanStyle!) 79 | } 80 | 81 | // 指定识别几种码 82 | if arrayCodeType == nil { 83 | arrayCodeType = [AVMetadataObject.ObjectType.qr as NSString, 84 | AVMetadataObject.ObjectType.ean13 as NSString, 85 | AVMetadataObject.ObjectType.code128 as NSString] as [AVMetadataObject.ObjectType] 86 | } 87 | 88 | scanObj = LBXScanWrapper(videoPreView: view, 89 | objType: arrayCodeType!, 90 | isCaptureImg: isNeedCodeImage, 91 | cropRect: cropRect, 92 | success: { [weak self] (arrayResult) -> Void in 93 | guard let strongSelf = self else { 94 | return 95 | } 96 | if !strongSelf.isSupportContinuous { 97 | // 停止扫描动画 98 | strongSelf.qRScanView?.stopScanAnimation() 99 | } 100 | strongSelf.handleCodeResult(arrayResult: arrayResult) 101 | }) 102 | } 103 | 104 | scanObj?.supportContinuous = isSupportContinuous; 105 | 106 | // 结束相机等待提示 107 | qRScanView?.deviceStopReadying() 108 | 109 | // 开始扫描动画 110 | qRScanView?.startScanAnimation() 111 | 112 | // 相机运行 113 | scanObj?.start() 114 | } 115 | 116 | open func drawScanView() { 117 | if qRScanView == nil { 118 | qRScanView = LBXScanView(frame: view.frame, vstyle: scanStyle!) 119 | view.addSubview(qRScanView!) 120 | delegate?.drawwed() 121 | } 122 | qRScanView?.deviceStartReadying(readyStr: readyString) 123 | } 124 | 125 | 126 | /** 127 | 处理扫码结果,如果是继承本控制器的,可以重写该方法,作出相应地处理,或者设置delegate作出相应处理 128 | */ 129 | open func handleCodeResult(arrayResult: [LBXScanResult]) { 130 | guard let delegate = scanResultDelegate else { 131 | fatalError("you must set scanResultDelegate or override this method without super keyword") 132 | } 133 | 134 | if !isSupportContinuous { 135 | navigationController?.popViewController(animated: true) 136 | 137 | } 138 | 139 | if let result = arrayResult.first { 140 | delegate.scanFinished(scanResult: result, error: nil) 141 | } else { 142 | let result = LBXScanResult(str: nil, img: nil, barCodeType: nil, corner: nil) 143 | delegate.scanFinished(scanResult: result, error: "no scan result") 144 | } 145 | } 146 | 147 | open override func viewWillDisappear(_ animated: Bool) { 148 | NSObject.cancelPreviousPerformRequests(withTarget: self) 149 | qRScanView?.stopScanAnimation() 150 | scanObj?.stop() 151 | } 152 | 153 | @objc open func openPhotoAlbum() { 154 | LBXPermissions.authorizePhotoWith { [weak self] _ in 155 | let picker = UIImagePickerController() 156 | picker.sourceType = UIImagePickerController.SourceType.photoLibrary 157 | picker.delegate = self 158 | picker.allowsEditing = true 159 | self?.present(picker, animated: true, completion: nil) 160 | } 161 | } 162 | } 163 | 164 | //MARK: - 图片选择代理方法 165 | extension LBXScanViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { 166 | 167 | //MARK: -----相册选择图片识别二维码 (条形码没有找到系统方法) 168 | public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { 169 | picker.dismiss(animated: true, completion: nil) 170 | 171 | let editedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage 172 | let originalImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage 173 | guard let image = editedImage ?? originalImage else { 174 | showMsg(title: nil, message: NSLocalizedString("Identify failed", comment: "Identify failed")) 175 | return 176 | } 177 | let arrayResult = LBXScanWrapper.recognizeQRImage(image: image) 178 | if !arrayResult.isEmpty { 179 | handleCodeResult(arrayResult: arrayResult) 180 | } 181 | } 182 | 183 | } 184 | 185 | //MARK: - 私有方法 186 | private extension LBXScanViewController { 187 | 188 | func showMsg(title: String?, message: String?) { 189 | let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert) 190 | let alertAction = UIAlertAction(title: NSLocalizedString("OK", comment: "OK"), style: .default, handler: nil) 191 | alertController.addAction(alertAction) 192 | present(alertController, animated: true, completion: nil) 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /Source/LBXScanViewStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanViewStyle.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/8. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 扫码区域动画效果 12 | public enum LBXScanViewAnimationStyle { 13 | case LineMove // 线条上下移动 14 | case NetGrid // 网格 15 | case LineStill // 线条停止在扫码区域中央 16 | case None // 无动画 17 | } 18 | 19 | /// 扫码区域4个角位置类型 20 | public enum LBXScanViewPhotoframeAngleStyle { 21 | case Inner // 内嵌,一般不显示矩形框情况下 22 | case Outer // 外嵌,包围在矩形框的4个角 23 | case On // 在矩形框的4个角上,覆盖 24 | } 25 | 26 | 27 | public struct LBXScanViewStyle { 28 | 29 | // MARK: - 中心位置矩形框 30 | 31 | /// 是否需要绘制扫码矩形框,默认YES 32 | public var isNeedShowRetangle = true 33 | 34 | /// 默认扫码区域为正方形,如果扫码区域不是正方形,设置宽高比 35 | public var whRatio: CGFloat = 1.0 36 | 37 | /// 矩形框(视频显示透明区)域向上移动偏移量,0表示扫码透明区域在当前视图中心位置,如果负值表示扫码区域下移 38 | public var centerUpOffset: CGFloat = 44 39 | 40 | /// 矩形框(视频显示透明区)域离界面左边及右边距离,默认60 41 | public var xScanRetangleOffset: CGFloat = 60 42 | 43 | /// 矩形框线条颜色,默认白色 44 | public var colorRetangleLine = UIColor.white 45 | 46 | /// 矩形框线条宽度,默认1 47 | public var widthRetangleLine: CGFloat = 1.0 48 | 49 | //MARK: - 矩形框(扫码区域)周围4个角 50 | 51 | /// 扫码区域的4个角类型 52 | public var photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Outer 53 | 54 | /// 4个角的颜色 55 | public var colorAngle = UIColor(red: 0.0, green: 167.0 / 255.0, blue: 231.0 / 255.0, alpha: 1.0) 56 | 57 | /// 扫码区域4个角的宽度和高度 58 | public var photoframeAngleW: CGFloat = 24.0 59 | public var photoframeAngleH: CGFloat = 24.0 60 | 61 | /// 扫码区域4个角的线条宽度,默认6,建议8到4之间 62 | public var photoframeLineW: CGFloat = 6 63 | 64 | //MARK: - 动画效果 65 | 66 | /// 扫码动画效果:线条或网格 67 | public var anmiationStyle = LBXScanViewAnimationStyle.LineMove 68 | 69 | /// 动画效果的图像,如线条或网格的图像 70 | public var animationImage: UIImage? 71 | 72 | //MARK: - 非识别区域颜色, 默认 RGBA (0,0,0,0.5),范围(0--1) 73 | 74 | public var color_NotRecoginitonArea = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5) 75 | 76 | public init() { } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /Source/LBXScanWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LBXScanWrapper.swift 3 | // swiftScan 4 | // 5 | // Created by lbxia on 15/12/10. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AVFoundation 11 | 12 | public struct LBXScanResult { 13 | 14 | /// 码内容 15 | public var strScanned: String? 16 | 17 | /// 扫描图像 18 | public var imgScanned: UIImage? 19 | 20 | /// 码的类型 21 | public var strBarCodeType: String? 22 | 23 | /// 码在图像中的位置 24 | public var arrayCorner: [AnyObject]? 25 | 26 | public init(str: String?, img: UIImage?, barCodeType: String?, corner: [AnyObject]?) { 27 | strScanned = str 28 | imgScanned = img 29 | strBarCodeType = barCodeType 30 | arrayCorner = corner 31 | } 32 | } 33 | 34 | 35 | 36 | open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate { 37 | 38 | let device = AVCaptureDevice.default(for: AVMediaType.video) 39 | var input: AVCaptureDeviceInput? 40 | var output: AVCaptureMetadataOutput 41 | 42 | let session = AVCaptureSession() 43 | var previewLayer: AVCaptureVideoPreviewLayer? 44 | var stillImageOutput: AVCaptureStillImageOutput 45 | 46 | // 存储返回结果 47 | var arrayResult = [LBXScanResult]() 48 | 49 | // 扫码结果返回block 50 | var successBlock: ([LBXScanResult]) -> Void 51 | 52 | // 是否需要拍照 53 | var isNeedCaptureImage: Bool 54 | 55 | // 当前扫码结果是否处理 56 | var isNeedScanResult = true 57 | 58 | //连续扫码 59 | var supportContinuous = false 60 | 61 | 62 | /** 63 | 初始化设备 64 | - parameter videoPreView: 视频显示UIView 65 | - parameter objType: 识别码的类型,缺省值 QR二维码 66 | - parameter isCaptureImg: 识别后是否采集当前照片 67 | - parameter cropRect: 识别区域 68 | - parameter success: 返回识别信息 69 | - returns: 70 | */ 71 | init(videoPreView: UIView, 72 | objType: [AVMetadataObject.ObjectType] = [(AVMetadataObject.ObjectType.qr as NSString) as AVMetadataObject.ObjectType], 73 | isCaptureImg: Bool, 74 | cropRect: CGRect = .zero, 75 | success: @escaping (([LBXScanResult]) -> Void)) { 76 | 77 | successBlock = success 78 | output = AVCaptureMetadataOutput() 79 | isNeedCaptureImage = isCaptureImg 80 | stillImageOutput = AVCaptureStillImageOutput() 81 | 82 | super.init() 83 | 84 | guard let device = device else { 85 | return 86 | } 87 | do { 88 | input = try AVCaptureDeviceInput(device: device) 89 | } catch let error as NSError { 90 | print("AVCaptureDeviceInput(): \(error)") 91 | } 92 | guard let input = input else { 93 | return 94 | } 95 | 96 | if session.canAddInput(input) { 97 | session.addInput(input) 98 | } 99 | 100 | if session.canAddOutput(output) { 101 | session.addOutput(output) 102 | } 103 | 104 | if session.canAddOutput(stillImageOutput) { 105 | session.addOutput(stillImageOutput) 106 | } 107 | 108 | stillImageOutput.outputSettings = [AVVideoCodecJPEG: AVVideoCodecKey] 109 | 110 | session.sessionPreset = AVCaptureSession.Preset.high 111 | 112 | // 参数设置 113 | output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) 114 | 115 | output.metadataObjectTypes = objType 116 | 117 | // output.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code] 118 | 119 | if !cropRect.equalTo(CGRect.zero) { 120 | // 启动相机后,直接修改该参数无效 121 | output.rectOfInterest = cropRect 122 | } 123 | 124 | previewLayer = AVCaptureVideoPreviewLayer(session: session) 125 | previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill 126 | 127 | var frame: CGRect = videoPreView.frame 128 | frame.origin = CGPoint.zero 129 | previewLayer?.frame = frame 130 | 131 | videoPreView.layer.insertSublayer(previewLayer!, at: 0) 132 | 133 | if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.continuousAutoFocus) { 134 | do { 135 | try input.device.lockForConfiguration() 136 | input.device.focusMode = AVCaptureDevice.FocusMode.continuousAutoFocus 137 | input.device.unlockForConfiguration() 138 | } catch let error as NSError { 139 | print("device.lockForConfiguration(): \(error)") 140 | } 141 | } 142 | } 143 | 144 | public func metadataOutput(_ output: AVCaptureMetadataOutput, 145 | didOutput metadataObjects: [AVMetadataObject], 146 | from connection: AVCaptureConnection) { 147 | captureOutput(output, didOutputMetadataObjects: metadataObjects, from: connection) 148 | } 149 | 150 | func start() { 151 | if !session.isRunning { 152 | isNeedScanResult = true 153 | session.startRunning() 154 | } 155 | } 156 | 157 | func stop() { 158 | if session.isRunning { 159 | isNeedScanResult = false 160 | session.stopRunning() 161 | } 162 | } 163 | 164 | open func captureOutput(_ captureOutput: AVCaptureOutput, 165 | didOutputMetadataObjects metadataObjects: [Any], 166 | from connection: AVCaptureConnection!) { 167 | guard isNeedScanResult else { 168 | // 上一帧处理中 169 | return 170 | } 171 | isNeedScanResult = false 172 | 173 | arrayResult.removeAll() 174 | 175 | // 识别扫码类型 176 | for current in metadataObjects { 177 | guard let code = current as? AVMetadataMachineReadableCodeObject else { 178 | continue 179 | } 180 | 181 | #if !targetEnvironment(simulator) 182 | 183 | arrayResult.append(LBXScanResult(str: code.stringValue, 184 | img: UIImage(), 185 | barCodeType: code.type.rawValue, 186 | corner: code.corners as [AnyObject]?)) 187 | #endif 188 | } 189 | 190 | if arrayResult.isEmpty || supportContinuous { 191 | isNeedScanResult = true 192 | } 193 | if !arrayResult.isEmpty { 194 | 195 | if supportContinuous { 196 | successBlock(arrayResult) 197 | } 198 | else if isNeedCaptureImage { 199 | captureImage() 200 | } else { 201 | stop() 202 | successBlock(arrayResult) 203 | } 204 | } 205 | } 206 | 207 | //MARK: ----拍照 208 | open func captureImage() { 209 | guard let stillImageConnection = connectionWithMediaType(mediaType: AVMediaType.video as AVMediaType, 210 | connections: stillImageOutput.connections as [AnyObject]) else { 211 | return 212 | } 213 | stillImageOutput.captureStillImageAsynchronously(from: stillImageConnection, completionHandler: { (imageDataSampleBuffer, _) -> Void in 214 | self.stop() 215 | if let imageDataSampleBuffer = imageDataSampleBuffer, 216 | let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) { 217 | 218 | let scanImg = UIImage(data: imageData) 219 | for idx in 0 ... self.arrayResult.count - 1 { 220 | self.arrayResult[idx].imgScanned = scanImg 221 | } 222 | } 223 | self.successBlock(self.arrayResult) 224 | }) 225 | } 226 | 227 | open func connectionWithMediaType(mediaType: AVMediaType, connections: [AnyObject]) -> AVCaptureConnection? { 228 | for connection in connections { 229 | guard let connectionTmp = connection as? AVCaptureConnection else { 230 | continue 231 | } 232 | for port in connectionTmp.inputPorts where port.mediaType == mediaType { 233 | return connectionTmp 234 | } 235 | } 236 | return nil 237 | } 238 | 239 | 240 | //MARK: 切换识别区域 241 | 242 | open func changeScanRect(cropRect: CGRect) { 243 | // 待测试,不知道是否有效 244 | stop() 245 | output.rectOfInterest = cropRect 246 | start() 247 | } 248 | 249 | //MARK: 切换识别码的类型 250 | open func changeScanType(objType: [AVMetadataObject.ObjectType]) { 251 | // 待测试中途修改是否有效 252 | output.metadataObjectTypes = objType 253 | } 254 | 255 | open func isGetFlash() -> Bool { 256 | return device != nil && device!.hasFlash && device!.hasTorch 257 | } 258 | 259 | /** 260 | 打开或关闭闪关灯 261 | - parameter torch: true:打开闪关灯 false:关闭闪光灯 262 | */ 263 | open func setTorch(torch: Bool) { 264 | guard isGetFlash() else { 265 | return 266 | } 267 | do { 268 | try input?.device.lockForConfiguration() 269 | input?.device.torchMode = torch ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off 270 | input?.device.unlockForConfiguration() 271 | } catch let error as NSError { 272 | print("device.lockForConfiguration(): \(error)") 273 | } 274 | } 275 | 276 | 277 | /// 闪光灯打开或关闭 278 | open func changeTorch() { 279 | let torch = input?.device.torchMode == .off 280 | setTorch(torch: torch) 281 | } 282 | 283 | //MARK: ------获取系统默认支持的码的类型 284 | static func defaultMetaDataObjectTypes() -> [AVMetadataObject.ObjectType] { 285 | var types = 286 | [ 287 | AVMetadataObject.ObjectType.qr, 288 | AVMetadataObject.ObjectType.upce, 289 | AVMetadataObject.ObjectType.code39, 290 | AVMetadataObject.ObjectType.code39Mod43, 291 | AVMetadataObject.ObjectType.ean13, 292 | AVMetadataObject.ObjectType.ean8, 293 | AVMetadataObject.ObjectType.code93, 294 | AVMetadataObject.ObjectType.code128, 295 | AVMetadataObject.ObjectType.pdf417, 296 | AVMetadataObject.ObjectType.aztec, 297 | ] 298 | // if #available(iOS 8.0, *) 299 | 300 | types.append(AVMetadataObject.ObjectType.interleaved2of5) 301 | types.append(AVMetadataObject.ObjectType.itf14) 302 | types.append(AVMetadataObject.ObjectType.dataMatrix) 303 | return types 304 | } 305 | 306 | /** 307 | 识别二维码码图像 308 | 309 | - parameter image: 二维码图像 310 | 311 | - returns: 返回识别结果 312 | */ 313 | public static func recognizeQRImage(image: UIImage) -> [LBXScanResult] { 314 | guard let cgImage = image.cgImage else { 315 | return [] 316 | } 317 | let detector = CIDetector(ofType: CIDetectorTypeQRCode, 318 | context: nil, 319 | options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])! 320 | let img = CIImage(cgImage: cgImage) 321 | let features = detector.features(in: img, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) 322 | return features.filter { 323 | $0.isKind(of: CIQRCodeFeature.self) 324 | }.map { 325 | $0 as! CIQRCodeFeature 326 | }.map { 327 | LBXScanResult(str: $0.messageString, 328 | img: image, 329 | barCodeType: AVMetadataObject.ObjectType.qr.rawValue, 330 | corner: nil) 331 | } 332 | } 333 | 334 | 335 | //MARK: -- - 生成二维码,背景色及二维码颜色设置 336 | public static func createCode(codeType: String, codeString: String, size: CGSize, qrColor: UIColor, bkColor: UIColor) -> UIImage? { 337 | let stringData = codeString.data(using: .utf8) 338 | 339 | // 系统自带能生成的码 340 | // CIAztecCodeGenerator 341 | // CICode128BarcodeGenerator 342 | // CIPDF417BarcodeGenerator 343 | // CIQRCodeGenerator 344 | let qrFilter = CIFilter(name: codeType) 345 | qrFilter?.setValue(stringData, forKey: "inputMessage") 346 | qrFilter?.setValue("H", forKey: "inputCorrectionLevel") 347 | 348 | // 上色 349 | let colorFilter = CIFilter(name: "CIFalseColor", 350 | parameters: [ 351 | "inputImage": qrFilter!.outputImage!, 352 | "inputColor0": CIColor(cgColor: qrColor.cgColor), 353 | "inputColor1": CIColor(cgColor: bkColor.cgColor), 354 | ] 355 | ) 356 | 357 | guard let qrImage = colorFilter?.outputImage, 358 | let cgImage = CIContext().createCGImage(qrImage, from: qrImage.extent) else { 359 | return nil 360 | } 361 | 362 | UIGraphicsBeginImageContext(size) 363 | let context = UIGraphicsGetCurrentContext()! 364 | context.interpolationQuality = CGInterpolationQuality.none 365 | context.scaleBy(x: 1.0, y: -1.0) 366 | context.draw(cgImage, in: context.boundingBoxOfClipPath) 367 | let codeImage = UIGraphicsGetImageFromCurrentImageContext() 368 | UIGraphicsEndImageContext() 369 | 370 | return codeImage 371 | } 372 | 373 | public static func createCode128(codeString: String, size: CGSize, qrColor: UIColor, bkColor: UIColor) -> UIImage? { 374 | let stringData = codeString.data(using: String.Encoding.utf8) 375 | 376 | // 系统自带能生成的码 377 | // CIAztecCodeGenerator 二维码 378 | // CICode128BarcodeGenerator 条形码 379 | // CIPDF417BarcodeGenerator 380 | // CIQRCodeGenerator 二维码 381 | let qrFilter = CIFilter(name: "CICode128BarcodeGenerator") 382 | qrFilter?.setDefaults() 383 | qrFilter?.setValue(stringData, forKey: "inputMessage") 384 | 385 | guard let outputImage = qrFilter?.outputImage else { 386 | return nil 387 | } 388 | let context = CIContext() 389 | guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { 390 | return nil 391 | } 392 | let image = UIImage(cgImage: cgImage, scale: 1.0, orientation: UIImage.Orientation.up) 393 | 394 | // Resize without interpolating 395 | return resizeImage(image: image, quality: CGInterpolationQuality.none, rate: 20.0) 396 | } 397 | 398 | 399 | // 根据扫描结果,获取图像中得二维码区域图像(如果相机拍摄角度故意很倾斜,获取的图像效果很差) 400 | static func getConcreteCodeImage(srcCodeImage: UIImage, codeResult: LBXScanResult) -> UIImage? { 401 | let rect = getConcreteCodeRectFromImage(srcCodeImage: srcCodeImage, codeResult: codeResult) 402 | guard !rect.isEmpty, let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect) else { 403 | return nil 404 | } 405 | return imageRotation(image: img, orientation: UIImage.Orientation.right) 406 | } 407 | 408 | // 根据二维码的区域截取二维码区域图像 409 | public static func getConcreteCodeImage(srcCodeImage: UIImage, rect: CGRect) -> UIImage? { 410 | guard !rect.isEmpty, let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect) else { 411 | return nil 412 | } 413 | return imageRotation(image: img, orientation: UIImage.Orientation.right) 414 | } 415 | 416 | // 获取二维码的图像区域 417 | public static func getConcreteCodeRectFromImage(srcCodeImage: UIImage, codeResult: LBXScanResult) -> CGRect { 418 | guard let corner = codeResult.arrayCorner as? [[String: Float]], corner.count >= 4 else { 419 | return .zero 420 | } 421 | 422 | let dicTopLeft = corner[0] 423 | let dicTopRight = corner[1] 424 | let dicBottomRight = corner[2] 425 | let dicBottomLeft = corner[3] 426 | 427 | let xLeftTopRatio = dicTopLeft["X"]! 428 | let yLeftTopRatio = dicTopLeft["Y"]! 429 | 430 | let xRightTopRatio = dicTopRight["X"]! 431 | let yRightTopRatio = dicTopRight["Y"]! 432 | 433 | let xBottomRightRatio = dicBottomRight["X"]! 434 | let yBottomRightRatio = dicBottomRight["Y"]! 435 | 436 | let xLeftBottomRatio = dicBottomLeft["X"]! 437 | let yLeftBottomRatio = dicBottomLeft["Y"]! 438 | 439 | // 由于截图只能矩形,所以截图不规则四边形的最大外围 440 | let xMinLeft = CGFloat(min(xLeftTopRatio, xLeftBottomRatio)) 441 | let xMaxRight = CGFloat(max(xRightTopRatio, xBottomRightRatio)) 442 | 443 | let yMinTop = CGFloat(min(yLeftTopRatio, yRightTopRatio)) 444 | let yMaxBottom = CGFloat(max(yLeftBottomRatio, yBottomRightRatio)) 445 | 446 | let imgW = srcCodeImage.size.width 447 | let imgH = srcCodeImage.size.height 448 | 449 | // 宽高反过来计算 450 | return CGRect(x: xMinLeft * imgH, 451 | y: yMinTop * imgW, 452 | width: (xMaxRight - xMinLeft) * imgH, 453 | height: (yMaxBottom - yMinTop) * imgW) 454 | } 455 | 456 | //MARK: ----图像处理 457 | 458 | /** 459 | 460 | @brief 图像中间加logo图片 461 | @param srcImg 原图像 462 | @param LogoImage logo图像 463 | @param logoSize logo图像尺寸 464 | @return 加Logo的图像 465 | */ 466 | public static func addImageLogo(srcImg: UIImage, logoImg: UIImage, logoSize: CGSize) -> UIImage { 467 | UIGraphicsBeginImageContext(srcImg.size) 468 | srcImg.draw(in: CGRect(x: 0, y: 0, width: srcImg.size.width, height: srcImg.size.height)) 469 | let rect = CGRect(x: srcImg.size.width / 2 - logoSize.width / 2, 470 | y: srcImg.size.height / 2 - logoSize.height / 2, 471 | width: logoSize.width, 472 | height: logoSize.height) 473 | logoImg.draw(in: rect) 474 | let resultingImage = UIGraphicsGetImageFromCurrentImageContext() 475 | UIGraphicsEndImageContext() 476 | return resultingImage! 477 | } 478 | 479 | //图像缩放 480 | static func resizeImage(image: UIImage, quality: CGInterpolationQuality, rate: CGFloat) -> UIImage? { 481 | var resized: UIImage? 482 | let width = image.size.width * rate 483 | let height = image.size.height * rate 484 | 485 | UIGraphicsBeginImageContext(CGSize(width: width, height: height)) 486 | let context = UIGraphicsGetCurrentContext() 487 | context?.interpolationQuality = quality 488 | image.draw(in: CGRect(x: 0, y: 0, width: width, height: height)) 489 | 490 | resized = UIGraphicsGetImageFromCurrentImageContext() 491 | UIGraphicsEndImageContext() 492 | 493 | return resized 494 | } 495 | 496 | // 图像裁剪 497 | static func imageByCroppingWithStyle(srcImg: UIImage, rect: CGRect) -> UIImage? { 498 | guard let imagePartRef = srcImg.cgImage?.cropping(to: rect) else { 499 | return nil 500 | } 501 | return UIImage(cgImage: imagePartRef) 502 | } 503 | 504 | // 图像旋转 505 | static func imageRotation(image: UIImage, orientation: UIImage.Orientation) -> UIImage { 506 | var rotate: Double = 0.0 507 | var rect: CGRect 508 | var translateX: CGFloat = 0.0 509 | var translateY: CGFloat = 0.0 510 | var scaleX: CGFloat = 1.0 511 | var scaleY: CGFloat = 1.0 512 | 513 | switch orientation { 514 | case .left: 515 | rotate = .pi / 2 516 | rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width) 517 | translateX = 0 518 | translateY = -rect.size.width 519 | scaleY = rect.size.width / rect.size.height 520 | scaleX = rect.size.height / rect.size.width 521 | case .right: 522 | rotate = 3 * .pi / 2 523 | rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width) 524 | translateX = -rect.size.height 525 | translateY = 0 526 | scaleY = rect.size.width / rect.size.height 527 | scaleX = rect.size.height / rect.size.width 528 | case .down: 529 | rotate = .pi 530 | rect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) 531 | translateX = -rect.size.width 532 | translateY = -rect.size.height 533 | default: 534 | rotate = 0.0 535 | rect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) 536 | translateX = 0 537 | translateY = 0 538 | } 539 | 540 | UIGraphicsBeginImageContext(rect.size) 541 | let context = UIGraphicsGetCurrentContext()! 542 | // 做CTM变换 543 | context.translateBy(x: 0.0, y: rect.size.height) 544 | context.scaleBy(x: 1.0, y: -1.0) 545 | context.rotate(by: CGFloat(rotate)) 546 | context.translateBy(x: translateX, y: translateY) 547 | 548 | context.scaleBy(x: scaleX, y: scaleY) 549 | // 绘制图片 550 | context.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height)) 551 | return UIGraphicsGetImageFromCurrentImageContext()! 552 | } 553 | 554 | } 555 | -------------------------------------------------------------------------------- /SwiftScanner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftScanner/SwiftScanner.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftScanner.h 3 | // SwiftScanner 4 | // 5 | // Created by 杨西川 on 16/09/2017. 6 | // Copyright © 2017 xialibing. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftScanner. 12 | FOUNDATION_EXPORT double SwiftScannerVersionNumber; 13 | 14 | //! Project version string for SwiftScanner. 15 | FOUNDATION_EXPORT const unsigned char SwiftScannerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /swiftScan.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'swiftScan' 3 | s.version = '1.2.1' 4 | s.summary = 'ios swift scan wrapper' 5 | s.homepage = 'https://github.com/MxABC/swiftScan' 6 | s.license = 'MIT' 7 | s.authors = {'MxABC' => 'lbxia20091227@foxmail.com'} 8 | s.platform = :ios, '8.0' 9 | s.source = {:git => 'https://github.com/MxABC/swiftScan.git', :tag => s.version} 10 | s.ios.deployment_target = "8.0" 11 | s.source_files = 'Source/*.swift' 12 | end 13 | -------------------------------------------------------------------------------- /swiftScan.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 488928AE1C1A6F4D005A8F83 /* swiftScan.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 488928AD1C1A6F4D005A8F83 /* swiftScan.podspec */; }; 11 | 488928E31C1A7BE4005A8F83 /* LBXScanLineAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928DD1C1A7BE4005A8F83 /* LBXScanLineAnimation.swift */; }; 12 | 488928E41C1A7BE4005A8F83 /* LBXScanNetAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928DE1C1A7BE4005A8F83 /* LBXScanNetAnimation.swift */; }; 13 | 488928E51C1A7BE4005A8F83 /* LBXScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928DF1C1A7BE4005A8F83 /* LBXScanView.swift */; }; 14 | 488928E61C1A7BE4005A8F83 /* LBXScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928E01C1A7BE4005A8F83 /* LBXScanViewController.swift */; }; 15 | 488928E71C1A7BE4005A8F83 /* LBXScanViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928E11C1A7BE4005A8F83 /* LBXScanViewStyle.swift */; }; 16 | 488928E81C1A7BE4005A8F83 /* LBXScanWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 488928E21C1A7BE4005A8F83 /* LBXScanWrapper.swift */; }; 17 | 48B143C41C17C98B00B2E7D5 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48B143C31C17C98B00B2E7D5 /* MainTableViewController.swift */; }; 18 | 48B143CA1C1809E700B2E7D5 /* CodeScan.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 48B143C91C1809E700B2E7D5 /* CodeScan.bundle */; }; 19 | 48D3BBD11C70104100823F87 /* LBXPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48D3BBD01C70104100823F87 /* LBXPermissions.swift */; }; 20 | 73FF0B8E1CF545FE0083F169 /* ScanResultController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 73FF0B8A1CF545FE0083F169 /* ScanResultController.xib */; }; 21 | 73FF0B8F1CF545FE0083F169 /* ScanResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FF0B8B1CF545FE0083F169 /* ScanResultController.swift */; }; 22 | 73FF0B901CF545FE0083F169 /* MyCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FF0B8C1CF545FE0083F169 /* MyCodeViewController.swift */; }; 23 | 73FF0B911CF545FE0083F169 /* QQScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FF0B8D1CF545FE0083F169 /* QQScanViewController.swift */; }; 24 | 7D42B9B01C05EE9A0084D045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D42B9AF1C05EE9A0084D045 /* AppDelegate.swift */; }; 25 | 7D42B9B21C05EE9A0084D045 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D42B9B11C05EE9A0084D045 /* ViewController.swift */; }; 26 | 7D42B9B51C05EE9A0084D045 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D42B9B31C05EE9A0084D045 /* Main.storyboard */; }; 27 | 7D42B9B71C05EE9A0084D045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D42B9B61C05EE9A0084D045 /* Assets.xcassets */; }; 28 | 7D42B9BA1C05EE9A0084D045 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7D42B9B81C05EE9A0084D045 /* LaunchScreen.storyboard */; }; 29 | 7DA82E091C19CE5E0028B5DB /* logo.JPG in Resources */ = {isa = PBXBuildFile; fileRef = 7DA82E081C19CE5E0028B5DB /* logo.JPG */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXCopyFilesBuildPhase section */ 33 | D6DC97001F6D0C0200E1CCEB /* Embed Frameworks */ = { 34 | isa = PBXCopyFilesBuildPhase; 35 | buildActionMask = 2147483647; 36 | dstPath = ""; 37 | dstSubfolderSpec = 10; 38 | files = ( 39 | ); 40 | name = "Embed Frameworks"; 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXCopyFilesBuildPhase section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | 488928AD1C1A6F4D005A8F83 /* swiftScan.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = swiftScan.podspec; sourceTree = ""; }; 47 | 488928DD1C1A7BE4005A8F83 /* LBXScanLineAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanLineAnimation.swift; sourceTree = ""; }; 48 | 488928DE1C1A7BE4005A8F83 /* LBXScanNetAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanNetAnimation.swift; sourceTree = ""; }; 49 | 488928DF1C1A7BE4005A8F83 /* LBXScanView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanView.swift; sourceTree = ""; }; 50 | 488928E01C1A7BE4005A8F83 /* LBXScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanViewController.swift; sourceTree = ""; }; 51 | 488928E11C1A7BE4005A8F83 /* LBXScanViewStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanViewStyle.swift; sourceTree = ""; }; 52 | 488928E21C1A7BE4005A8F83 /* LBXScanWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXScanWrapper.swift; sourceTree = ""; }; 53 | 48B143C31C17C98B00B2E7D5 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = ""; }; 54 | 48B143C91C1809E700B2E7D5 /* CodeScan.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = CodeScan.bundle; sourceTree = ""; }; 55 | 48D3BBD01C70104100823F87 /* LBXPermissions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LBXPermissions.swift; sourceTree = ""; }; 56 | 73FF0B8A1CF545FE0083F169 /* ScanResultController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ScanResultController.xib; sourceTree = ""; }; 57 | 73FF0B8B1CF545FE0083F169 /* ScanResultController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanResultController.swift; sourceTree = ""; }; 58 | 73FF0B8C1CF545FE0083F169 /* MyCodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyCodeViewController.swift; sourceTree = ""; }; 59 | 73FF0B8D1CF545FE0083F169 /* QQScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QQScanViewController.swift; sourceTree = ""; }; 60 | 7D42B9AC1C05EE9A0084D045 /* swiftScan.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = swiftScan.app; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 7D42B9AF1C05EE9A0084D045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 62 | 7D42B9B11C05EE9A0084D045 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 63 | 7D42B9B41C05EE9A0084D045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 64 | 7D42B9B61C05EE9A0084D045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 65 | 7D42B9B91C05EE9A0084D045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 66 | 7D42B9BB1C05EE9A0084D045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 67 | 7D46320C1C18683A00D70CF1 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; 68 | 7D46320D1C18683A00D70CF1 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; 69 | 7DA82E081C19CE5E0028B5DB /* logo.JPG */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = logo.JPG; sourceTree = ""; }; 70 | D6DC96F61F6D0C0200E1CCEB /* SwiftScanner.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftScanner.h; sourceTree = ""; }; 71 | D6DC96F71F6D0C0200E1CCEB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 72 | /* End PBXFileReference section */ 73 | 74 | /* Begin PBXFrameworksBuildPhase section */ 75 | 7D42B9A91C05EE9A0084D045 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | /* End PBXFrameworksBuildPhase section */ 83 | 84 | /* Begin PBXGroup section */ 85 | 488928DC1C1A7BE4005A8F83 /* Source */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 48D3BBD01C70104100823F87 /* LBXPermissions.swift */, 89 | 488928DD1C1A7BE4005A8F83 /* LBXScanLineAnimation.swift */, 90 | 488928DE1C1A7BE4005A8F83 /* LBXScanNetAnimation.swift */, 91 | 488928DF1C1A7BE4005A8F83 /* LBXScanView.swift */, 92 | 488928E01C1A7BE4005A8F83 /* LBXScanViewController.swift */, 93 | 488928E11C1A7BE4005A8F83 /* LBXScanViewStyle.swift */, 94 | 488928E21C1A7BE4005A8F83 /* LBXScanWrapper.swift */, 95 | ); 96 | path = Source; 97 | sourceTree = ""; 98 | }; 99 | 7D42B9A31C05EE9A0084D045 = { 100 | isa = PBXGroup; 101 | children = ( 102 | 488928AD1C1A6F4D005A8F83 /* swiftScan.podspec */, 103 | 488928DC1C1A7BE4005A8F83 /* Source */, 104 | 7D42B9AE1C05EE9A0084D045 /* swiftScan */, 105 | D6DC96F51F6D0C0200E1CCEB /* SwiftScanner */, 106 | 7D42B9AD1C05EE9A0084D045 /* Products */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 7D42B9AD1C05EE9A0084D045 /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 7D42B9AC1C05EE9A0084D045 /* swiftScan.app */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 7D42B9AE1C05EE9A0084D045 /* swiftScan */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 73FF0B8A1CF545FE0083F169 /* ScanResultController.xib */, 122 | 73FF0B8B1CF545FE0083F169 /* ScanResultController.swift */, 123 | 73FF0B8C1CF545FE0083F169 /* MyCodeViewController.swift */, 124 | 73FF0B8D1CF545FE0083F169 /* QQScanViewController.swift */, 125 | 7DA82E081C19CE5E0028B5DB /* logo.JPG */, 126 | 48B143C91C1809E700B2E7D5 /* CodeScan.bundle */, 127 | 7D42B9AF1C05EE9A0084D045 /* AppDelegate.swift */, 128 | 7D42B9B11C05EE9A0084D045 /* ViewController.swift */, 129 | 7D42B9B31C05EE9A0084D045 /* Main.storyboard */, 130 | 7D42B9B61C05EE9A0084D045 /* Assets.xcassets */, 131 | 7D42B9B81C05EE9A0084D045 /* LaunchScreen.storyboard */, 132 | 7D42B9BB1C05EE9A0084D045 /* Info.plist */, 133 | 48B143C31C17C98B00B2E7D5 /* MainTableViewController.swift */, 134 | ); 135 | path = swiftScan; 136 | sourceTree = ""; 137 | }; 138 | D6DC96F51F6D0C0200E1CCEB /* SwiftScanner */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D6DC96F61F6D0C0200E1CCEB /* SwiftScanner.h */, 142 | D6DC96F71F6D0C0200E1CCEB /* Info.plist */, 143 | ); 144 | path = SwiftScanner; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | 7D42B9AB1C05EE9A0084D045 /* swiftScan */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = 7D42B9BE1C05EE9A0084D045 /* Build configuration list for PBXNativeTarget "swiftScan" */; 153 | buildPhases = ( 154 | 7D42B9A81C05EE9A0084D045 /* Sources */, 155 | 7D42B9A91C05EE9A0084D045 /* Frameworks */, 156 | 7D42B9AA1C05EE9A0084D045 /* Resources */, 157 | D6DC97001F6D0C0200E1CCEB /* Embed Frameworks */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = swiftScan; 164 | productName = swiftScan; 165 | productReference = 7D42B9AC1C05EE9A0084D045 /* swiftScan.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | /* End PBXNativeTarget section */ 169 | 170 | /* Begin PBXProject section */ 171 | 7D42B9A41C05EE9A0084D045 /* Project object */ = { 172 | isa = PBXProject; 173 | attributes = { 174 | LastSwiftUpdateCheck = 0710; 175 | LastUpgradeCheck = 1000; 176 | ORGANIZATIONNAME = xialibing; 177 | TargetAttributes = { 178 | 7D42B9AB1C05EE9A0084D045 = { 179 | CreatedOnToolsVersion = 7.1; 180 | DevelopmentTeam = 8LQ7CL73D8; 181 | LastSwiftMigration = 0820; 182 | ProvisioningStyle = Automatic; 183 | }; 184 | }; 185 | }; 186 | buildConfigurationList = 7D42B9A71C05EE9A0084D045 /* Build configuration list for PBXProject "swiftScan" */; 187 | compatibilityVersion = "Xcode 3.2"; 188 | developmentRegion = en; 189 | hasScannedForEncodings = 0; 190 | knownRegions = ( 191 | en, 192 | Base, 193 | "zh-Hans", 194 | ); 195 | mainGroup = 7D42B9A31C05EE9A0084D045; 196 | productRefGroup = 7D42B9AD1C05EE9A0084D045 /* Products */; 197 | projectDirPath = ""; 198 | projectRoot = ""; 199 | targets = ( 200 | 7D42B9AB1C05EE9A0084D045 /* swiftScan */, 201 | ); 202 | }; 203 | /* End PBXProject section */ 204 | 205 | /* Begin PBXResourcesBuildPhase section */ 206 | 7D42B9AA1C05EE9A0084D045 /* Resources */ = { 207 | isa = PBXResourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | 48B143CA1C1809E700B2E7D5 /* CodeScan.bundle in Resources */, 211 | 7D42B9BA1C05EE9A0084D045 /* LaunchScreen.storyboard in Resources */, 212 | 7D42B9B71C05EE9A0084D045 /* Assets.xcassets in Resources */, 213 | 73FF0B8E1CF545FE0083F169 /* ScanResultController.xib in Resources */, 214 | 7DA82E091C19CE5E0028B5DB /* logo.JPG in Resources */, 215 | 7D42B9B51C05EE9A0084D045 /* Main.storyboard in Resources */, 216 | 488928AE1C1A6F4D005A8F83 /* swiftScan.podspec in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | 7D42B9A81C05EE9A0084D045 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 488928E61C1A7BE4005A8F83 /* LBXScanViewController.swift in Sources */, 228 | 73FF0B911CF545FE0083F169 /* QQScanViewController.swift in Sources */, 229 | 48B143C41C17C98B00B2E7D5 /* MainTableViewController.swift in Sources */, 230 | 7D42B9B21C05EE9A0084D045 /* ViewController.swift in Sources */, 231 | 488928E51C1A7BE4005A8F83 /* LBXScanView.swift in Sources */, 232 | 488928E81C1A7BE4005A8F83 /* LBXScanWrapper.swift in Sources */, 233 | 7D42B9B01C05EE9A0084D045 /* AppDelegate.swift in Sources */, 234 | 73FF0B901CF545FE0083F169 /* MyCodeViewController.swift in Sources */, 235 | 488928E71C1A7BE4005A8F83 /* LBXScanViewStyle.swift in Sources */, 236 | 488928E41C1A7BE4005A8F83 /* LBXScanNetAnimation.swift in Sources */, 237 | 73FF0B8F1CF545FE0083F169 /* ScanResultController.swift in Sources */, 238 | 488928E31C1A7BE4005A8F83 /* LBXScanLineAnimation.swift in Sources */, 239 | 48D3BBD11C70104100823F87 /* LBXPermissions.swift in Sources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | /* End PBXSourcesBuildPhase section */ 244 | 245 | /* Begin PBXVariantGroup section */ 246 | 7D42B9B31C05EE9A0084D045 /* Main.storyboard */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | 7D42B9B41C05EE9A0084D045 /* Base */, 250 | 7D46320C1C18683A00D70CF1 /* zh-Hans */, 251 | ); 252 | name = Main.storyboard; 253 | sourceTree = ""; 254 | }; 255 | 7D42B9B81C05EE9A0084D045 /* LaunchScreen.storyboard */ = { 256 | isa = PBXVariantGroup; 257 | children = ( 258 | 7D42B9B91C05EE9A0084D045 /* Base */, 259 | 7D46320D1C18683A00D70CF1 /* zh-Hans */, 260 | ); 261 | name = LaunchScreen.storyboard; 262 | sourceTree = ""; 263 | }; 264 | /* End PBXVariantGroup section */ 265 | 266 | /* Begin XCBuildConfiguration section */ 267 | 7D42B9BC1C05EE9A0084D045 /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 277 | CLANG_WARN_BOOL_CONVERSION = YES; 278 | CLANG_WARN_COMMA = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 281 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 282 | CLANG_WARN_EMPTY_BODY = YES; 283 | CLANG_WARN_ENUM_CONVERSION = YES; 284 | CLANG_WARN_INFINITE_RECURSION = YES; 285 | CLANG_WARN_INT_CONVERSION = YES; 286 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 287 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 288 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 289 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 290 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 291 | CLANG_WARN_STRICT_PROTOTYPES = YES; 292 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 296 | COPY_PHASE_STRIP = NO; 297 | DEBUG_INFORMATION_FORMAT = dwarf; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | ENABLE_TESTABILITY = YES; 300 | GCC_C_LANGUAGE_STANDARD = gnu99; 301 | GCC_DYNAMIC_NO_PIC = NO; 302 | GCC_NO_COMMON_BLOCKS = YES; 303 | GCC_OPTIMIZATION_LEVEL = 0; 304 | GCC_PREPROCESSOR_DEFINITIONS = ( 305 | "DEBUG=1", 306 | "$(inherited)", 307 | ); 308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 310 | GCC_WARN_UNDECLARED_SELECTOR = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 312 | GCC_WARN_UNUSED_FUNCTION = YES; 313 | GCC_WARN_UNUSED_VARIABLE = YES; 314 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 315 | MTL_ENABLE_DEBUG_INFO = YES; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = iphoneos; 318 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 319 | SWIFT_VERSION = 3.0; 320 | }; 321 | name = Debug; 322 | }; 323 | 7D42B9BD1C05EE9A0084D045 /* Release */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 328 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 329 | CLANG_CXX_LIBRARY = "libc++"; 330 | CLANG_ENABLE_MODULES = YES; 331 | CLANG_ENABLE_OBJC_ARC = YES; 332 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 333 | CLANG_WARN_BOOL_CONVERSION = YES; 334 | CLANG_WARN_COMMA = YES; 335 | CLANG_WARN_CONSTANT_CONVERSION = YES; 336 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_EMPTY_BODY = YES; 339 | CLANG_WARN_ENUM_CONVERSION = YES; 340 | CLANG_WARN_INFINITE_RECURSION = YES; 341 | CLANG_WARN_INT_CONVERSION = YES; 342 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 344 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 345 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 346 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 347 | CLANG_WARN_STRICT_PROTOTYPES = YES; 348 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 349 | CLANG_WARN_UNREACHABLE_CODE = YES; 350 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 351 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 352 | COPY_PHASE_STRIP = NO; 353 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 354 | ENABLE_NS_ASSERTIONS = NO; 355 | ENABLE_STRICT_OBJC_MSGSEND = YES; 356 | GCC_C_LANGUAGE_STANDARD = gnu99; 357 | GCC_NO_COMMON_BLOCKS = YES; 358 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 359 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 360 | GCC_WARN_UNDECLARED_SELECTOR = YES; 361 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 362 | GCC_WARN_UNUSED_FUNCTION = YES; 363 | GCC_WARN_UNUSED_VARIABLE = YES; 364 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 365 | MTL_ENABLE_DEBUG_INFO = NO; 366 | SDKROOT = iphoneos; 367 | SWIFT_COMPILATION_MODE = wholemodule; 368 | SWIFT_VERSION = 3.0; 369 | VALIDATE_PRODUCT = YES; 370 | }; 371 | name = Release; 372 | }; 373 | 7D42B9BF1C05EE9A0084D045 /* Debug */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 378 | CODE_SIGN_IDENTITY = "iPhone Developer"; 379 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 380 | CODE_SIGN_STYLE = Automatic; 381 | DEVELOPMENT_TEAM = 8LQ7CL73D8; 382 | INFOPLIST_FILE = swiftScan/Info.plist; 383 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 385 | PRODUCT_BUNDLE_IDENTIFIER = com.lbx.hk2019235; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | PROVISIONING_PROFILE = "5afb03a3-32bd-412b-9db2-5fa2d3271415"; 388 | PROVISIONING_PROFILE_SPECIFIER = ""; 389 | SWIFT_VERSION = 5.0; 390 | }; 391 | name = Debug; 392 | }; 393 | 7D42B9C01C05EE9A0084D045 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 397 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 398 | CODE_SIGN_IDENTITY = "iPhone Developer"; 399 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 400 | CODE_SIGN_STYLE = Automatic; 401 | DEVELOPMENT_TEAM = LM3HW8FY8K; 402 | INFOPLIST_FILE = swiftScan/Info.plist; 403 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 404 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 405 | PRODUCT_BUNDLE_IDENTIFIER = com.51shaoxi.github.swiftScan; 406 | PRODUCT_NAME = "$(TARGET_NAME)"; 407 | PROVISIONING_PROFILE = "5afb03a3-32bd-412b-9db2-5fa2d3271415"; 408 | PROVISIONING_PROFILE_SPECIFIER = ""; 409 | SWIFT_VERSION = 5.0; 410 | }; 411 | name = Release; 412 | }; 413 | /* End XCBuildConfiguration section */ 414 | 415 | /* Begin XCConfigurationList section */ 416 | 7D42B9A71C05EE9A0084D045 /* Build configuration list for PBXProject "swiftScan" */ = { 417 | isa = XCConfigurationList; 418 | buildConfigurations = ( 419 | 7D42B9BC1C05EE9A0084D045 /* Debug */, 420 | 7D42B9BD1C05EE9A0084D045 /* Release */, 421 | ); 422 | defaultConfigurationIsVisible = 0; 423 | defaultConfigurationName = Release; 424 | }; 425 | 7D42B9BE1C05EE9A0084D045 /* Build configuration list for PBXNativeTarget "swiftScan" */ = { 426 | isa = XCConfigurationList; 427 | buildConfigurations = ( 428 | 7D42B9BF1C05EE9A0084D045 /* Debug */, 429 | 7D42B9C01C05EE9A0084D045 /* Release */, 430 | ); 431 | defaultConfigurationIsVisible = 0; 432 | defaultConfigurationName = Release; 433 | }; 434 | /* End XCConfigurationList section */ 435 | }; 436 | rootObject = 7D42B9A41C05EE9A0084D045 /* Project object */; 437 | } 438 | -------------------------------------------------------------------------------- /swiftScan.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /swiftScan.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /swiftScan.xcodeproj/xcshareddata/xcschemes/SwiftScanner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /swiftScan/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/11/25. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 17 | 18 | // window? = UIWindow() 19 | // window?.frame = UIScreen.main.bounds; 20 | // 21 | // window?.rootViewController = UINavigationController(rootViewController: MainTableViewController()) 22 | // 23 | // window?.makeKeyAndVisible(); 24 | return true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /swiftScan/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /swiftScan/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /swiftScan/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/device_scan@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/device_scan@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_Scan_weixin_Line@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_Scan_weixin_Line@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_flash_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_flash_down@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_flash_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_flash_nor@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_myqrcode_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_myqrcode_down@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_myqrcode_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_myqrcode_nor@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_photo_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_photo_down@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_photo_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_photo_nor@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_btn_scan_off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_btn_scan_off@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_full_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_full_net.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_light_green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_light_green@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_part_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_part_net.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_titlebar_back_nor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_titlebar_back_nor@2x.png -------------------------------------------------------------------------------- /swiftScan/CodeScan.bundle/qrcode_scan_titlebar_back_pressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/CodeScan.bundle/qrcode_scan_titlebar_back_pressed@2x.png -------------------------------------------------------------------------------- /swiftScan/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppleMusicUsageDescription 26 | 请点击“允许”以允许访问 27 | NSBluetoothPeripheralUsageDescription 28 | 请点击“允许”以允许访问 29 | NSCalendarsUsageDescription 30 | 请点击“允许”以允许访问 31 | NSCameraUsageDescription 32 | 请点击“允许”以允许访问 33 | NSHealthShareUsageDescription 34 | 请点击“允许”以允许访问 35 | NSHealthUpdateUsageDescription 36 | 请点击“允许”以允许访问 37 | NSLocationAlwaysUsageDescription 38 | 请点击“允许”以允许访问 39 | NSLocationUsageDescription 40 | 请点击“允许”以允许访问 41 | NSLocationWhenInUseUsageDescription 42 | 请点击“允许”以允许访问 43 | NSMicrophoneUsageDescription 44 | 请点击“允许”以允许访问 45 | NSMotionUsageDescription 46 | 请点击“允许”以允许访问 47 | NSPhotoLibraryAddUsageDescription 48 | 请允许访问您的相册 49 | NSPhotoLibraryUsageDescription 50 | 请点击“允许”以允许访问 51 | NSRemindersUsageDescription 52 | 请点击“允许”以允许访问 53 | UILaunchStoryboardName 54 | LaunchScreen 55 | UIMainStoryboardFile 56 | Main 57 | UIRequiredDeviceCapabilities 58 | 59 | armv7 60 | 61 | UISupportedInterfaceOrientations 62 | 63 | UIInterfaceOrientationPortrait 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /swiftScan/MainTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableViewController.swift 3 | // swiftScan 4 | // 5 | // Created by lbxia on 15/12/9. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | import AVFoundation 12 | 13 | class MainTableViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 14 | 15 | var arrayItems: Array> = [ 16 | ["模拟qq扫码界面", "qqStyle"], 17 | ["模仿支付宝扫码区域", "ZhiFuBaoStyle"], 18 | ["模仿微信扫码区域", "weixinStyle"], 19 | ["无边框,内嵌4个角", "InnerStyle"], 20 | ["4个角在矩形框线上,网格动画", "OnStyle"], 21 | ["自定义颜色", "changeColor"], 22 | ["只识别框内", "recoCropRect"], 23 | ["改变尺寸", "changeSize"], 24 | ["条形码效果", "notSquare"], 25 | ["二维码/条形码生成", "myCode"], 26 | ["相册", "openLocalPhotoAlbum"] 27 | ] 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | 32 | self.title = "swift 扫一扫" 33 | 34 | self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuseIdentifier") 35 | self.tableView.delegate = self 36 | self.tableView.dataSource = self 37 | } 38 | 39 | // MARK: - Table view data source 40 | 41 | func numberOfSectionsInTableView(tableView: UITableView) -> Int { 42 | // #warning Incomplete implementation, return the number of sections 43 | return 1 44 | } 45 | 46 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 47 | // #warning Incomplete implementation, return the number of rows 48 | return arrayItems.count 49 | } 50 | 51 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 52 | let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath as IndexPath) 53 | 54 | // Configure the cell... 55 | cell.textLabel?.text = arrayItems[indexPath.row].first 56 | 57 | return cell 58 | } 59 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 60 | 61 | //objc_msgSend对应方法好像没有 62 | let sel = NSSelectorFromString(arrayItems[indexPath.row].last!) 63 | 64 | self.InnerStyle() 65 | 66 | tableView.deselectRow(at: indexPath as IndexPath, animated: true) 67 | 68 | } 69 | 70 | // MARK: - ---模仿qq扫码界面--------- 71 | func qqStyle() { 72 | print("qqStyle") 73 | 74 | let vc = QQScanViewController() 75 | var style = LBXScanViewStyle() 76 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 77 | vc.scanStyle = style 78 | self.navigationController?.pushViewController(vc, animated: true) 79 | 80 | } 81 | 82 | // MARK: - --模仿支付宝------ 83 | func ZhiFuBaoStyle() { 84 | //设置扫码区域参数 85 | var style = LBXScanViewStyle() 86 | 87 | style.centerUpOffset = 60 88 | style.xScanRetangleOffset = 30 89 | 90 | if UIScreen.main.bounds.size.height <= 480 { 91 | //3.5inch 显示的扫码缩小 92 | style.centerUpOffset = 40 93 | style.xScanRetangleOffset = 20 94 | } 95 | 96 | style.color_NotRecoginitonArea = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 0.4) 97 | 98 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 99 | style.photoframeLineW = 2.0 100 | style.photoframeAngleW = 16 101 | style.photoframeAngleH = 16 102 | 103 | style.isNeedShowRetangle = false 104 | 105 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 106 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_full_net") 107 | 108 | let vc = LBXScanViewController() 109 | 110 | vc.scanStyle = style 111 | self.navigationController?.pushViewController(vc, animated: true) 112 | 113 | } 114 | 115 | func createImageWithColor(color: UIColor) -> UIImage { 116 | let rect=CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0) 117 | UIGraphicsBeginImageContext(rect.size) 118 | let context = UIGraphicsGetCurrentContext() 119 | context!.setFillColor(color.cgColor) 120 | context!.fill(rect) 121 | let theImage = UIGraphicsGetImageFromCurrentImageContext() 122 | UIGraphicsEndImageContext() 123 | return theImage! 124 | } 125 | 126 | // MARK: - ------条形码扫码界面 --------- 127 | func notSquare() { 128 | //设置扫码区域参数 129 | //设置扫码区域参数 130 | var style = LBXScanViewStyle() 131 | 132 | style.centerUpOffset = 44 133 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 134 | style.photoframeLineW = 4 135 | style.photoframeAngleW = 28 136 | style.photoframeAngleH = 16 137 | style.isNeedShowRetangle = false 138 | 139 | style.anmiationStyle = LBXScanViewAnimationStyle.LineStill 140 | 141 | style.animationImage = createImageWithColor(color: UIColor.red) 142 | //非正方形 143 | //设置矩形宽高比 144 | style.whRatio = 4.3/2.18 145 | 146 | //离左边和右边距离 147 | style.xScanRetangleOffset = 30 148 | 149 | let vc = LBXScanViewController() 150 | 151 | vc.scanStyle = style 152 | self.navigationController?.pushViewController(vc, animated: true) 153 | 154 | } 155 | 156 | // MARK: - ---无边框,内嵌4个角 ----- 157 | func InnerStyle() { 158 | //设置扫码区域参数 159 | var style = LBXScanViewStyle() 160 | style.centerUpOffset = 44 161 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 162 | style.photoframeLineW = 3 163 | style.photoframeAngleW = 18 164 | style.photoframeAngleH = 18 165 | style.isNeedShowRetangle = false 166 | 167 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 168 | 169 | //qq里面的线条图片 170 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 171 | 172 | let vc = LBXScanViewController() 173 | vc.scanStyle = style 174 | self.navigationController?.pushViewController(vc, animated: true) 175 | 176 | } 177 | 178 | // MARK: - --无边框,内嵌4个角------ 179 | func weixinStyle() { 180 | //设置扫码区域参数 181 | var style = LBXScanViewStyle() 182 | style.centerUpOffset = 44 183 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 184 | style.photoframeLineW = 2 185 | style.photoframeAngleW = 18 186 | style.photoframeAngleH = 18 187 | style.isNeedShowRetangle = false 188 | 189 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 190 | 191 | style.colorAngle = UIColor(red: 0.0/255, green: 200.0/255.0, blue: 20.0/255.0, alpha: 1.0) 192 | 193 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_Scan_weixin_Line") 194 | 195 | let vc = LBXScanViewController() 196 | vc.scanStyle = style 197 | self.navigationController?.pushViewController(vc, animated: true) 198 | } 199 | 200 | // MARK: - ---框内区域识别 201 | func recoCropRect() { 202 | //设置扫码区域参数 203 | var style = LBXScanViewStyle() 204 | style.centerUpOffset = 44 205 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 206 | style.photoframeLineW = 6 207 | style.photoframeAngleW = 24 208 | style.photoframeAngleH = 24 209 | style.isNeedShowRetangle = true 210 | 211 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 212 | 213 | //矩形框离左边缘及右边缘的距离 214 | style.xScanRetangleOffset = 80 215 | 216 | //使用的支付宝里面网格图片 217 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_part_net") 218 | 219 | let vc = LBXScanViewController() 220 | vc.scanStyle = style 221 | 222 | vc.isOpenInterestRect = true 223 | //TODO:待设置框内识别 224 | self.navigationController?.pushViewController(vc, animated: true) 225 | 226 | } 227 | 228 | // MARK: - ----4个角在矩形框线上,网格动画 229 | func OnStyle() { 230 | //设置扫码区域参数 231 | var style = LBXScanViewStyle() 232 | style.centerUpOffset = 44 233 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 234 | style.photoframeLineW = 6 235 | style.photoframeAngleW = 24 236 | style.photoframeAngleH = 24 237 | style.isNeedShowRetangle = true 238 | 239 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 240 | 241 | //使用的支付宝里面网格图片 242 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_part_net") 243 | 244 | let vc = LBXScanViewController() 245 | vc.scanStyle = style 246 | self.navigationController?.pushViewController(vc, animated: true) 247 | 248 | } 249 | 250 | // MARK: - ------自定义4个角及矩形框颜色 251 | func changeColor() { 252 | //设置扫码区域参数 253 | var style = LBXScanViewStyle() 254 | style.centerUpOffset = 44 255 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 256 | style.photoframeLineW = 6 257 | style.photoframeAngleW = 24 258 | style.photoframeAngleH = 24 259 | style.isNeedShowRetangle = true 260 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 261 | 262 | //使用的支付宝里面网格图片 263 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 264 | 265 | //4个角的颜色 266 | style.colorAngle = UIColor(red: 65.0/255.0, green: 174.0/255.0, blue: 57.0/255.0, alpha: 1.0) 267 | 268 | //矩形框颜色 269 | style.colorRetangleLine = UIColor(red: 247.0/255.0, green: 202.0/255.0, blue: 15.0/255.0, alpha: 1.0) 270 | 271 | //非矩形框区域颜色 272 | style.color_NotRecoginitonArea = UIColor(red: 247.0/255.0, green: 202.0/255.0, blue: 15.0/255.0, alpha: 0.2) 273 | 274 | let vc = LBXScanViewController() 275 | vc.scanStyle = style 276 | 277 | self.navigationController?.pushViewController(vc, animated: true) 278 | 279 | } 280 | 281 | // MARK: - -----改变扫码区域位置 282 | func changeSize() { 283 | //设置扫码区域参数 284 | var style = LBXScanViewStyle() 285 | 286 | //矩形框向上移动 287 | style.centerUpOffset = 60 288 | //矩形框离左边缘及右边缘的距离 289 | style.xScanRetangleOffset = 100 290 | 291 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 292 | style.photoframeLineW = 6 293 | style.photoframeAngleW = 24 294 | style.photoframeAngleH = 24 295 | style.isNeedShowRetangle = true 296 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 297 | 298 | //qq里面的线条图片 299 | 300 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 301 | let vc = LBXScanViewController() 302 | vc.scanStyle = style 303 | 304 | self.navigationController?.pushViewController(vc, animated: true) 305 | 306 | } 307 | 308 | // MARK: - ------- 相册 309 | func openLocalPhotoAlbum() { 310 | let picker = UIImagePickerController() 311 | 312 | 313 | picker.sourceType = UIImagePickerController.SourceType.photoLibrary 314 | 315 | picker.delegate = self; 316 | 317 | 318 | picker.allowsEditing = true 319 | 320 | present(picker, animated: true, completion: nil) 321 | } 322 | 323 | // MARK: - ----相册选择图片识别二维码 (条形码没有找到系统方法) 324 | func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: AnyObject]) { 325 | picker.dismiss(animated: true, completion: nil) 326 | 327 | var image:UIImage? = info[UIImagePickerController.InfoKey.editedImage.rawValue] as? UIImage 328 | 329 | if (image == nil ) 330 | { 331 | image = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage 332 | } 333 | 334 | if(image == nil) { 335 | return 336 | } 337 | 338 | if(image != nil) { 339 | let arrayResult = LBXScanWrapper.recognizeQRImage(image: image!) 340 | if arrayResult.count > 0 { 341 | let result = arrayResult[0] 342 | 343 | showMsg(title: result.strBarCodeType, message: result.strScanned) 344 | 345 | return 346 | } 347 | } 348 | showMsg(title: "", message: "识别失败") 349 | } 350 | 351 | 352 | func showMsg(title:String?,message:String?) 353 | { 354 | let alertController = UIAlertController(title: title, message:message, preferredStyle: UIAlertController.Style.alert) 355 | 356 | let alertAction = UIAlertAction(title: "知道了", style: UIAlertAction.Style.default) { (alertAction) -> Void in 357 | 358 | } 359 | 360 | alertController.addAction(alertAction) 361 | 362 | present(alertController, animated: true, completion: nil) 363 | } 364 | 365 | func myCode() { 366 | let vc = MyCodeViewController() 367 | self.navigationController?.pushViewController(vc, animated: true) 368 | } 369 | 370 | } 371 | -------------------------------------------------------------------------------- /swiftScan/MyCodeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyCodeViewController.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/10. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MyCodeViewController: UIViewController { 12 | 13 | //二维码 14 | var qrView = UIView() 15 | var qrImgView = UIImageView() 16 | 17 | //条形码 18 | var tView = UIView() 19 | var tImgView = UIImageView() 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | // Do any additional setup after loading the view. 25 | view.backgroundColor = UIColor.white 26 | 27 | drawCodeShowView() 28 | 29 | createQR1() 30 | 31 | createCode128() 32 | } 33 | 34 | // MARK: - -----二维码、条形码显示位置 35 | func drawCodeShowView() { 36 | //二维码 37 | 38 | let rect = CGRect(x: (self.view.frame.width-self.view.frame.width*5/6)/2, y: 100, width: self.view.frame.width*5/6, height: self.view.frame.width*5/6) 39 | qrView.frame = rect 40 | self.view.addSubview(qrView) 41 | 42 | qrView.backgroundColor = UIColor.white 43 | qrView.layer.shadowOffset = CGSize(width: 0, height: 2) 44 | qrView.layer.shadowRadius = 2 45 | qrView.layer.shadowColor = UIColor.black.cgColor 46 | qrView.layer.shadowOpacity = 0.5 47 | 48 | qrImgView.bounds = CGRect(x: 0, y: 0, width: qrView.frame.width-12, height: qrView.frame.width-12) 49 | qrImgView.center = CGPoint(x: qrView.frame.width/2, y: qrView.frame.height/2) 50 | qrView .addSubview(qrImgView) 51 | 52 | //条形码 53 | tView.frame = CGRect(x: (self.view.frame.width-self.view.frame.width*5/6)/2, 54 | y: rect.maxY+20, 55 | width: self.view.frame.width*5/6, 56 | height: self.view.frame.width*5/6*0.5) 57 | self.view .addSubview(tView) 58 | tView.layer.shadowOffset = CGSize(width: 0, height: 2) 59 | tView.layer.shadowRadius = 2 60 | tView.layer.shadowColor = UIColor.black.cgColor 61 | tView.layer.shadowOpacity = 0.5 62 | 63 | tImgView.bounds = CGRect(x: 0, y: 0, width: tView.frame.width-12, height: tView.frame.height-12) 64 | tImgView.center = CGPoint(x: tView.frame.width/2, y: tView.frame.height/2) 65 | tView .addSubview(tImgView) 66 | 67 | } 68 | 69 | func createQR1() { 70 | // qrView.hidden = false 71 | // tView.hidden = true 72 | 73 | let qrImg = LBXScanWrapper.createCode(codeType: "CIQRCodeGenerator", codeString: "lbxia20091227@foxmail.com", size: qrImgView.bounds.size, qrColor: UIColor.black, bkColor: UIColor.white) 74 | 75 | let logoImg = UIImage(named: "logo.JPG") 76 | qrImgView.image = LBXScanWrapper.addImageLogo(srcImg: qrImg!, logoImg: logoImg!, logoSize: CGSize(width: 30, height: 30)) 77 | } 78 | 79 | func createCode128() { 80 | 81 | let qrImg = LBXScanWrapper.createCode128(codeString: "005103906002", size: qrImgView.bounds.size, qrColor: UIColor.black, bkColor: UIColor.white) 82 | 83 | tImgView.image = qrImg 84 | 85 | } 86 | 87 | deinit { 88 | print("MyCodeViewController deinit") 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /swiftScan/QQScanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QQScanViewController.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/10. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class QQScanViewController: LBXScanViewController { 12 | 13 | /** 14 | @brief 扫码区域上方提示文字 15 | */ 16 | var topTitle: UILabel? 17 | 18 | /** 19 | @brief 闪关灯开启状态 20 | */ 21 | var isOpenedFlash: Bool = false 22 | 23 | // MARK: - 底部几个功能:开启闪光灯、相册、我的二维码 24 | 25 | //底部显示的功能项 26 | var bottomItemsView: UIView? 27 | 28 | //相册 29 | var btnPhoto: UIButton = UIButton() 30 | 31 | //闪光灯 32 | var btnFlash: UIButton = UIButton() 33 | 34 | //我的二维码 35 | var btnMyQR: UIButton = UIButton() 36 | 37 | override func viewDidLoad() { 38 | super.viewDidLoad() 39 | 40 | //需要识别后的图像 41 | setNeedCodeImage(needCodeImg: true) 42 | 43 | //框向上移动10个像素 44 | scanStyle?.centerUpOffset += 10 45 | 46 | // Do any additional setup after loading the view. 47 | } 48 | 49 | override func viewDidAppear(_ animated: Bool) { 50 | 51 | super.viewDidAppear(animated) 52 | 53 | drawBottomItems() 54 | } 55 | 56 | override func handleCodeResult(arrayResult: [LBXScanResult]) { 57 | 58 | for result: LBXScanResult in arrayResult { 59 | if let str = result.strScanned { 60 | print(str) 61 | } 62 | } 63 | 64 | let result: LBXScanResult = arrayResult[0] 65 | 66 | let vc = ScanResultController() 67 | vc.codeResult = result 68 | navigationController?.pushViewController(vc, animated: true) 69 | } 70 | 71 | func drawBottomItems() { 72 | if (bottomItemsView != nil) { 73 | 74 | return 75 | } 76 | 77 | let yMax = self.view.frame.maxY - self.view.frame.minY 78 | 79 | bottomItemsView = UIView(frame: CGRect(x: 0.0, y: yMax-100, width: self.view.frame.size.width, height: 100 ) ) 80 | 81 | bottomItemsView!.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.6) 82 | 83 | self.view .addSubview(bottomItemsView!) 84 | 85 | let size = CGSize(width: 65, height: 87) 86 | 87 | self.btnFlash = UIButton() 88 | btnFlash.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height) 89 | btnFlash.center = CGPoint(x: bottomItemsView!.frame.width/2, y: bottomItemsView!.frame.height/2) 90 | 91 | btnFlash.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_flash_nor"), for:UIControl.State.normal) 92 | btnFlash.addTarget(self, action: #selector(QQScanViewController.openOrCloseFlash), for: UIControl.Event.touchUpInside) 93 | 94 | 95 | self.btnPhoto = UIButton() 96 | btnPhoto.bounds = btnFlash.bounds 97 | btnPhoto.center = CGPoint(x: bottomItemsView!.frame.width/4, y: bottomItemsView!.frame.height/2) 98 | btnPhoto.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_photo_nor"), for: UIControl.State.normal) 99 | btnPhoto.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_photo_down"), for: UIControl.State.highlighted) 100 | // btnPhoto.addTarget(self, action: Selector(("openPhotoAlbum")), for: UIControlEvents.touchUpInside) 101 | 102 | btnPhoto.addTarget(self, action: #selector(openPhotoAlbum), for: UIControl.Event.touchUpInside) 103 | 104 | self.btnMyQR = UIButton() 105 | btnMyQR.bounds = btnFlash.bounds; 106 | btnMyQR.center = CGPoint(x: bottomItemsView!.frame.width * 3/4, y: bottomItemsView!.frame.height/2); 107 | btnMyQR.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_myqrcode_nor"), for: UIControl.State.normal) 108 | btnMyQR.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_myqrcode_down"), for: UIControl.State.highlighted) 109 | btnMyQR.addTarget(self, action: #selector(myCode), for: UIControl.Event.touchUpInside) 110 | 111 | 112 | bottomItemsView?.addSubview(btnFlash) 113 | bottomItemsView?.addSubview(btnPhoto) 114 | bottomItemsView?.addSubview(btnMyQR) 115 | 116 | view.addSubview(bottomItemsView!) 117 | } 118 | 119 | //开关闪光灯 120 | @objc func openOrCloseFlash() { 121 | scanObj?.changeTorch() 122 | 123 | isOpenedFlash = !isOpenedFlash 124 | 125 | if isOpenedFlash 126 | { 127 | btnFlash.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_flash_down"), for:UIControl.State.normal) 128 | } 129 | else 130 | { 131 | btnFlash.setImage(UIImage(named: "CodeScan.bundle/qrcode_scan_btn_flash_nor"), for:UIControl.State.normal) 132 | 133 | } 134 | } 135 | 136 | @objc func myCode() { 137 | let vc = MyCodeViewController() 138 | self.navigationController?.pushViewController(vc, animated: true) 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /swiftScan/ScanResultController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScanResultController.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/12/11. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ScanResultController: UIViewController { 12 | 13 | @IBOutlet weak var codeImg: UIImageView! 14 | @IBOutlet weak var codeTypeLabel: UILabel! 15 | @IBOutlet weak var codeStringLabel: UILabel! 16 | @IBOutlet weak var concreteCodeImg: UIImageView! 17 | 18 | var codeResult: LBXScanResult? 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | self.edgesForExtendedLayout = UIRectEdge(rawValue: 0) 24 | 25 | codeTypeLabel.text = "" 26 | codeStringLabel.text = "" 27 | 28 | // Do any additional setup after loading the view. 29 | } 30 | 31 | override func viewDidAppear(_ animated: Bool) { 32 | super.viewDidAppear(animated) 33 | 34 | codeImg.image = codeResult?.imgScanned 35 | codeTypeLabel.text = "码的类型:" + (codeResult?.strBarCodeType)! 36 | codeStringLabel.text = "码的内容:" + (codeResult?.strScanned)! 37 | 38 | if codeImg.image != nil { 39 | 40 | } 41 | } 42 | 43 | func zoomRect( rect:inout CGRect, srcImg: UIImage) { 44 | rect.origin.x -= 10 45 | rect.origin.y -= 10 46 | rect.size.width += 20 47 | rect.size.height += 20 48 | 49 | if rect.origin.x < 0 { 50 | rect.origin.x = 0 51 | } 52 | 53 | if (rect.origin.y < 0) { 54 | rect.origin.y = 0 55 | } 56 | 57 | if (rect.origin.x + rect.size.width) > srcImg.size.width { 58 | rect.size.width = srcImg.size.width - rect.origin.x - 1 59 | } 60 | 61 | if (rect.origin.y + rect.size.height) > srcImg.size.height { 62 | rect.size.height = srcImg.size.height - rect.origin.y - 1 63 | } 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /swiftScan/ScanResultController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 37 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 63 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /swiftScan/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // swiftScan 4 | // 5 | // Created by xialibing on 15/11/25. 6 | // Copyright © 2015年 xialibing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIImagePickerControllerDelegate, UINavigationControllerDelegate, LBXScanViewControllerDelegate { 12 | var tableView: UITableView! 13 | 14 | var arrayItems: Array> = [ 15 | ["模拟qq扫码界面", "qqStyle"], 16 | ["模仿支付宝扫码区域", "ZhiFuBaoStyle"], 17 | ["模仿微信扫码区域", "weixinStyle"], 18 | ["无边框,内嵌4个角", "InnerStyle"], 19 | ["4个角在矩形框线上,网格动画", "OnStyle"], 20 | ["自定义颜色", "changeColor"], 21 | ["只识别框内", "recoCropRect"], 22 | ["改变尺寸", "changeSize"], 23 | ["条形码效果", "notSquare"], 24 | ["二维码/条形码生成", "myCode"], 25 | ["相册", "openLocalPhotoAlbum"] 26 | ] 27 | 28 | var isSupportContinuous = false; 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | tableView = UITableView(frame: CGRect(x: 0, y: 20, width: view.frame.width, height: view.frame.height)) 33 | self.title = "swift 扫一扫" 34 | tableView.delegate = self 35 | tableView.dataSource = self 36 | self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuseIdentifier") 37 | view.addSubview(tableView) 38 | } 39 | 40 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 41 | // #warning Incomplete implementation, return the number of rows 42 | return arrayItems.count 43 | } 44 | 45 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 46 | let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath as IndexPath) 47 | // Configure the cell... 48 | cell.textLabel?.text = arrayItems[indexPath.row].first 49 | 50 | return cell 51 | } 52 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 53 | 54 | //objc_msgSend对应方法好像没有 55 | 56 | if indexPath.row == 10 { 57 | openLocalPhotoAlbum() 58 | return 59 | } 60 | 61 | isSupportContinuous = false; 62 | 63 | switch indexPath.row { 64 | case 0: 65 | self.qqStyle() 66 | case 1: 67 | self.ZhiFuBaoStyle() 68 | case 2: 69 | self.weixinStyle() 70 | case 3: 71 | self.InnerStyle() 72 | case 4: 73 | self.OnStyle() 74 | case 5: 75 | self.changeColor() 76 | case 6: 77 | self.recoCropRect() 78 | case 7: 79 | self.changeSize() 80 | case 8: 81 | self.notSquare() 82 | case 9: 83 | self.myCode() 84 | case 10: 85 | self.openLocalPhotoAlbum() 86 | default: 87 | break 88 | } 89 | 90 | tableView.deselectRow(at: indexPath as IndexPath, animated: true) 91 | 92 | } 93 | 94 | // MARK: - ---模仿qq扫码界面--------- 95 | func qqStyle() { 96 | print("qqStyle") 97 | 98 | let vc = QQScanViewController() 99 | var style = LBXScanViewStyle() 100 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 101 | vc.scanStyle = style 102 | self.navigationController?.pushViewController(vc, animated: true) 103 | 104 | } 105 | 106 | // MARK: - --模仿支付宝------ 107 | func ZhiFuBaoStyle() { 108 | //设置扫码区域参数 109 | var style = LBXScanViewStyle() 110 | 111 | style.centerUpOffset = 60 112 | style.xScanRetangleOffset = 30 113 | 114 | if UIScreen.main.bounds.size.height <= 480 { 115 | //3.5inch 显示的扫码缩小 116 | style.centerUpOffset = 40 117 | style.xScanRetangleOffset = 20 118 | } 119 | 120 | style.color_NotRecoginitonArea = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 0.4) 121 | 122 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 123 | style.photoframeLineW = 2.0 124 | style.photoframeAngleW = 16 125 | style.photoframeAngleH = 16 126 | 127 | style.isNeedShowRetangle = false 128 | 129 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 130 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_full_net") 131 | 132 | let vc = LBXScanViewController() 133 | 134 | vc.scanStyle = style 135 | vc.isSupportContinuous = true; 136 | 137 | isSupportContinuous = true; 138 | 139 | vc.scanResultDelegate = self 140 | 141 | self.navigationController?.pushViewController(vc, animated: true) 142 | 143 | } 144 | 145 | func createImageWithColor(color: UIColor) -> UIImage { 146 | let rect=CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0) 147 | UIGraphicsBeginImageContext(rect.size) 148 | let context = UIGraphicsGetCurrentContext() 149 | context!.setFillColor(color.cgColor) 150 | context!.fill(rect) 151 | let theImage = UIGraphicsGetImageFromCurrentImageContext() 152 | UIGraphicsEndImageContext() 153 | return theImage! 154 | } 155 | 156 | // MARK: - ------条形码扫码界面 --------- 157 | func notSquare() { 158 | //设置扫码区域参数 159 | //设置扫码区域参数 160 | var style = LBXScanViewStyle() 161 | 162 | style.centerUpOffset = 44 163 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 164 | style.photoframeLineW = 4 165 | style.photoframeAngleW = 28 166 | style.photoframeAngleH = 16 167 | style.isNeedShowRetangle = false 168 | 169 | style.anmiationStyle = LBXScanViewAnimationStyle.LineStill 170 | 171 | style.animationImage = createImageWithColor(color: UIColor.red) 172 | //非正方形 173 | //设置矩形宽高比 174 | style.whRatio = 4.3/2.18 175 | 176 | //离左边和右边距离 177 | style.xScanRetangleOffset = 30 178 | 179 | let vc = LBXScanViewController() 180 | vc.scanResultDelegate = self 181 | 182 | vc.scanStyle = style 183 | self.navigationController?.pushViewController(vc, animated: true) 184 | 185 | } 186 | 187 | // MARK: - ---无边框,内嵌4个角 ----- 188 | func InnerStyle() { 189 | //设置扫码区域参数 190 | var style = LBXScanViewStyle() 191 | style.centerUpOffset = 44 192 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 193 | style.photoframeLineW = 3 194 | style.photoframeAngleW = 18 195 | style.photoframeAngleH = 18 196 | style.isNeedShowRetangle = false 197 | 198 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 199 | 200 | //qq里面的线条图片 201 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 202 | 203 | let vc = LBXScanViewController() 204 | vc.scanStyle = style 205 | vc.scanResultDelegate = self 206 | self.navigationController?.pushViewController(vc, animated: true) 207 | 208 | } 209 | 210 | // MARK: - --无边框,内嵌4个角------ 211 | func weixinStyle() { 212 | //设置扫码区域参数 213 | var style = LBXScanViewStyle() 214 | style.centerUpOffset = 44 215 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner 216 | style.photoframeLineW = 2 217 | style.photoframeAngleW = 18 218 | style.photoframeAngleH = 18 219 | style.isNeedShowRetangle = false 220 | 221 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 222 | 223 | style.colorAngle = UIColor(red: 0.0/255, green: 200.0/255.0, blue: 20.0/255.0, alpha: 1.0) 224 | 225 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_Scan_weixin_Line") 226 | 227 | let vc = LBXScanViewController() 228 | vc.scanStyle = style 229 | vc.scanResultDelegate = self 230 | self.navigationController?.pushViewController(vc, animated: true) 231 | } 232 | 233 | // MARK: - ---框内区域识别 234 | func recoCropRect() { 235 | //设置扫码区域参数 236 | var style = LBXScanViewStyle() 237 | style.centerUpOffset = 44 238 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 239 | style.photoframeLineW = 6 240 | style.photoframeAngleW = 24 241 | style.photoframeAngleH = 24 242 | style.isNeedShowRetangle = true 243 | 244 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 245 | 246 | //矩形框离左边缘及右边缘的距离 247 | style.xScanRetangleOffset = 80 248 | 249 | //使用的支付宝里面网格图片 250 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_part_net") 251 | 252 | let vc = LBXScanViewController() 253 | vc.scanStyle = style 254 | 255 | vc.isOpenInterestRect = true 256 | vc.scanResultDelegate = self 257 | 258 | //TODO:待设置框内识别 259 | self.navigationController?.pushViewController(vc, animated: true) 260 | 261 | } 262 | 263 | // MARK: - ----4个角在矩形框线上,网格动画 264 | func OnStyle() { 265 | //设置扫码区域参数 266 | var style = LBXScanViewStyle() 267 | style.centerUpOffset = 44 268 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 269 | style.photoframeLineW = 6 270 | style.photoframeAngleW = 24 271 | style.photoframeAngleH = 24 272 | style.isNeedShowRetangle = true 273 | 274 | style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid 275 | 276 | //使用的支付宝里面网格图片 277 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_part_net") 278 | 279 | let vc = LBXScanViewController() 280 | vc.scanStyle = style 281 | vc.scanResultDelegate = self 282 | 283 | self.navigationController?.pushViewController(vc, animated: true) 284 | 285 | } 286 | 287 | // MARK: - ------自定义4个角及矩形框颜色 288 | func changeColor() { 289 | //设置扫码区域参数 290 | var style = LBXScanViewStyle() 291 | style.centerUpOffset = 44 292 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 293 | style.photoframeLineW = 6 294 | style.photoframeAngleW = 24 295 | style.photoframeAngleH = 24 296 | style.isNeedShowRetangle = true 297 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 298 | 299 | //使用的支付宝里面网格图片 300 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 301 | 302 | //4个角的颜色 303 | style.colorAngle = UIColor(red: 65.0/255.0, green: 174.0/255.0, blue: 57.0/255.0, alpha: 1.0) 304 | 305 | //矩形框颜色 306 | style.colorRetangleLine = UIColor(red: 247.0/255.0, green: 202.0/255.0, blue: 15.0/255.0, alpha: 1.0) 307 | 308 | //非矩形框区域颜色 309 | style.color_NotRecoginitonArea = UIColor(red: 247.0/255.0, green: 202.0/255.0, blue: 15.0/255.0, alpha: 0.2) 310 | 311 | let vc = LBXScanViewController() 312 | vc.scanStyle = style 313 | vc.readyString = "相机启动中..." 314 | vc.scanResultDelegate = self 315 | 316 | self.navigationController?.pushViewController(vc, animated: true) 317 | 318 | } 319 | 320 | // MARK: - -----改变扫码区域位置 321 | func changeSize() { 322 | //设置扫码区域参数 323 | var style = LBXScanViewStyle() 324 | 325 | //矩形框向上移动 326 | style.centerUpOffset = 60 327 | //矩形框离左边缘及右边缘的距离 328 | style.xScanRetangleOffset = 100 329 | 330 | style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On 331 | style.photoframeLineW = 6 332 | style.photoframeAngleW = 24 333 | style.photoframeAngleH = 24 334 | style.isNeedShowRetangle = true 335 | style.anmiationStyle = LBXScanViewAnimationStyle.LineMove 336 | 337 | //qq里面的线条图片 338 | 339 | style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_light_green") 340 | let vc = LBXScanViewController() 341 | vc.scanStyle = style 342 | vc.scanResultDelegate = self 343 | 344 | self.navigationController?.pushViewController(vc, animated: true) 345 | 346 | } 347 | 348 | // MARK: - ------- 相册 349 | func openLocalPhotoAlbum() { 350 | 351 | LBXPermissions.authorizePhotoWith { [weak self] (granted) in 352 | 353 | if granted { 354 | if let strongSelf = self { 355 | let picker = UIImagePickerController() 356 | 357 | picker.sourceType = UIImagePickerController.SourceType.photoLibrary 358 | picker.delegate = self; 359 | 360 | picker.allowsEditing = true 361 | strongSelf.present(picker, animated: true, completion: nil) 362 | } 363 | } else { 364 | LBXPermissions.jumpToSystemPrivacySetting() 365 | } 366 | } 367 | } 368 | 369 | // MARK: - ----相册选择图片识别二维码 (条形码没有找到系统方法) 370 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 371 | picker.dismiss(animated: true, completion: nil) 372 | 373 | var image:UIImage? = info[UIImagePickerController.InfoKey.editedImage] as? UIImage 374 | 375 | if (image == nil ) 376 | { 377 | image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage 378 | } 379 | 380 | if(image == nil) { 381 | return 382 | } 383 | 384 | if(image != nil) { 385 | let arrayResult = LBXScanWrapper.recognizeQRImage(image: image!) 386 | if arrayResult.count > 0 { 387 | let result = arrayResult[0] 388 | 389 | showMsg(title: result.strBarCodeType, message: result.strScanned) 390 | 391 | return 392 | } 393 | } 394 | showMsg(title: "", message: "识别失败") 395 | } 396 | 397 | 398 | func showMsg(title:String?,message:String?) 399 | { 400 | let alertController = UIAlertController(title: title, message:message, preferredStyle: UIAlertController.Style.alert) 401 | 402 | let alertAction = UIAlertAction(title: "知道了", style: UIAlertAction.Style.default) { (alertAction) -> Void in 403 | 404 | 405 | } 406 | 407 | alertController.addAction(alertAction) 408 | 409 | present(alertController, animated: true, completion: nil) 410 | } 411 | 412 | func myCode() { 413 | let vc = MyCodeViewController() 414 | self.navigationController?.pushViewController(vc, animated: true) 415 | } 416 | 417 | func scanFinished(scanResult: LBXScanResult, error: String?) { 418 | NSLog("scanResult:\(scanResult)") 419 | 420 | 421 | 422 | if !isSupportContinuous { 423 | 424 | DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400)) { 425 | let vc = ScanResultController() 426 | vc.codeResult = scanResult 427 | self.navigationController?.pushViewController(vc, animated: true) 428 | } 429 | } 430 | 431 | } 432 | 433 | } 434 | -------------------------------------------------------------------------------- /swiftScan/logo.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MxABC/swiftScan/b0cc9aea11140125b75d1baaccb16c9567cdf69a/swiftScan/logo.JPG -------------------------------------------------------------------------------- /swiftScan/zh-Hans.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /swiftScan/zh-Hans.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------