用AVFoundation实现扫描二维码功能

需要用到的只要几个类:

AVCaptureSession:管理输入和输出流,包含开启和停止会话方法

AVCaptureDeviceInput:是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化

AVCaptureDevice:代表了物理捕获设备如摄像机。

AVCaptureMetadataOutput:是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。

AVCaptureVideoPreviewLayer:CALayer的一个子类,显示捕获到的相机输出流。

 

用一张图来解释着几个类在具体工作时时如何协调的:


解释一下:首先我们需要一个AVCaptureSession会话,这个是连接输入数据和输出数据的桥梁:


会话创建好了,我们还会需要输入和输出对象:

    //输入设备
    privatelazy var deviceInput: AVCaptureDeviceInput?= {
        // 获取摄像头
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        do {
            // 创建输入对象
            let device = try AVCaptureDeviceInput.init(device: device)
            return device
        }catch {
            print(error)
            let fatal:NSError = error as NSError
            // 没有权限访问相机
            if fatal.code == -11852 {
                let alert = UIAlertController.init(title:"微博没有权限访问您的相机", message: "请您进入设置-隐私-相机为我们开启权限", preferredStyle: UIAlertControllerStyle.Alert)
                alert.addAction(UIAlertAction.init(title:"我知道了", style: UIAlertActionStyle.Default,handler: nil))
                self.presentViewController(alert,animated: true, completion: nil)
           }
            return nil
       }
   }()
   
    //输出对象
    privatelazy var outPut: AVCaptureMetadataOutput= AVCaptureMetadataOutput()


预览视图:

 private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        let layer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session:self.session)
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()

由此,输入设备,会话,输出,预览视图都已准备就绪,然后开始进行二维码的扫描:

 

// MARK:开始扫描二维码
    privatefunc startScan() {
        // 1、判断是否能够将输入添加到会话中
        if !session.canAddInput(deviceInput) {
            return
       }
        // 2、判断是否能够将输出添加到会话中
        if !session.canAddOutput(outPut) {
            return
       }
        // 3、将输入和输出都添加到会话中
        session.addInput(deviceInput)
        session.addOutput(outPut)
       
        // 4、设置输出能够解析的数据类型(默认包含二维码类型)
        // 这个设置必须是在输出对象被添加到会话之后
        outPut.metadataObjectTypes = outPut.availableMetadataObjectTypes
        print(outPut.availableMetadataObjectTypes)
        // 5、设置输出对象的代理,只要解析成功就会通知这个代理
        outPut.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
       
        // 添加预览视图
        view.layer.insertSublayer(previewLayer, atIndex:0)
       
        // 6、告诉session开始扫描
        session.startRunning()
   }

注意第五步中我们将self设置为了输出对象的代理点开这个协议你会发现只有一个代理方法


这个方法只要相机扫描到可以解析的数据就会被调用,扫描结果储存在metadataObjects这个数组中,由于现在我们只需要二维码,所以

加一些判断:

    func captureOutput(captureOutput: AVCaptureOutput!,didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!){
        print(metadataObjects)
        if metadataObjects.count > 0 {
            let code: AVMetadataMachineReadableCodeObject = metadataObjects.lastas!AVMetadataMachineReadableCodeObject
            let type = code.type
            if type.containsString("QRCode") {
                // 扫描结果为二维码
                let result = code.stringValue
                handleResult(result)
            }else {
                return
           }
       }
   }


然后再加一个处理结果方法打开链接:

 

   /**
     处理扫描结果
    
     - parameter result: 扫描结果
    */
    func handleResult(result: String) {
        // 停止扫描
        stopScan()
        // 打开地址
        if UIApplication.sharedApplication().canOpenURL(NSURL.init(string: result)!) {
            UIApplication.sharedApplication().openURL(NSURL.init(string: result)!)
       }
   }
 
    /**
     停止扫描
    */
    func stopScan() {
        self.scanImage.layer.removeAllAnimations()
        session.stopRunning()
        session.removeInput(deviceInput)
        session.removeOutput(outPut)
        // 预览图层从视图层中移除
        previewLayer.removeFromSuperlayer()
   }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值