现在苹果iOS系统已经原生支持了二维码扫描的功能,使用原生来扫描需要导入 AVFoundation 。
扫描准备
一、获取摄像设备:
1 device = AVCaptureDevice .defaultDevice(withMediaType: AVMediaTypeVideo )
二、创建输入流
1 2 3 4 5 do { try input = AVCaptureDeviceInput (device: device) } catch let e as NSError { print (e.localizedDescription) }
三、创建输出流
1 2 3 output = AVCaptureMetadataOutput () output? .setMetadataObjectsDelegate(self , queue: DispatchQueue .main)
四、初始化连接对象
1 2 3 4 5 session = AVCaptureSession () session? .canSetSessionPreset(AVCaptureSessionPresetHigh ) session? .addOutput(output) session? .addInput(input)
五、设置扫描区域
1 2 3 4 5 6 let x = ((SCREENHeight - QRCodeWidth - topViewHeight) / 2.0 ) / SCREENHeight let y = ((SCREENWidth - QRCodeWidth ) / 2.0 ) / SCREENWidth let width = QRCodeWidth / SCREENHeight let height = QRCodeWidth / SCREENWidth output? .rectOfInterest = CGRect (x: x, y: y, width: width, height: height)
六、设置扫码支持的编码格式(如下设置条形码和二维码兼容)
1 output? .metadataObjectTypes = [AVMetadataObjectTypeQRCode , AVMetadataObjectTypeEAN13Code , AVMetadataObjectTypeEAN8Code , AVMetadataObjectTypeCode128Code ]
七、开始捕获
1 2 3 4 5 preview = AVCaptureVideoPreviewLayer (session: session) preview? .videoGravity = AVLayerVideoGravityResizeAspectFill preview? .frame = self .view.layer.bounds self .view.layer.insertSublayer(preview! , at: 0 )session? .startRunning()
扫描动画
这里的动画是仿支付宝的扫描框动画
我们新建一个方法,专门处理我们的动画。
1 2 3 4 5 6 7 8 9 10 11 12 13 fileprivate func scanAnimation () -> CABasicAnimation { let scanNetAnimation = CABasicAnimation () scanNetAnimation.keyPath = "transform.translation.y" scanNetAnimation.byValue = QRCodeWidth scanNetAnimation.duration = 1.5 scanNetAnimation.repeatCount = MAXFLOAT return scanNetAnimation }
使用动画:
我们在创建界面的时候,扫描框有一个UIImageView,我们需要将我们的动画添加到这个ImageView上面。
1 scanImageView? .layer.add(scanAnimation(), forKey: nil )
扫描之后的处理
1 2 3 4 5 6 7 8 9 10 func captureOutput (_ captureOutput : AVCaptureOutput !, didOutputMetadataObjects metadataObjects : [Any ]! , from connection : AVCaptureConnection !) { if metadataObjects.count > 0 { session? .stopRunning() let metadataObject = metadataObjects[0 ] as AnyObject let stringValue: String = metadataObject.stringValue let vc = QRCodeResultViewController .instantiate() vc.resultStr = stringValue self .navigationController? .pushViewController(vc, animated: true ) } }
点击扫描结果的处理
1 2 3 4 5 6 7 8 9 func webView (_ webView : UIWebView , shouldStartLoadWith request : URLRequest , navigationType : UIWebViewNavigationType ) -> Bool { let requestURL = request.url if requestURL? .scheme == "http" || requestURL? .scheme == "https" || requestURL? .scheme == "mailto" && navigationType == .linkClicked { let svc = SFSafariViewController (url: requestURL! ) self .present(svc, animated: true , completion: nil ) } return true }
我们可以用
1 open func open (_ url : URL , options : [String : Any ] = [:], completionHandler completion : ((Bool ) -> Swift .Void )? = nil )
在Safari中打开连接。不过最好是把事件控制在自己的程序中,在iOS 9 之后,苹果引入了 SFSafariViewController 这个类,可以用这个类来显示需要浏览的网页。
1 2 let svc = SFSafariViewController (url: requestURL! )self .present(svc, animated: true , completion: nil )