使用 AVFoundation 在 Swift 3.0 中扫描条码或二维码 [英] Scanning Barcode or QR code in Swift 3.0 using AVFoundation

查看:18
本文介绍了使用 AVFoundation 在 Swift 3.0 中扫描条码或二维码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注这个

然后系统在要求用户允许访问时显示目的字符串:

有关它的更多信息,您可以使用这篇文章:

我对您的 BarcodeViewController 做了一些修改以使其正常工作,如下所示:

<块引用>

BarcodeViewController

导入 UIKit导入 AVFoundation协议 BarcodeDelegate {func 条码读取(条码:字符串)}类 BarcodeViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {var 委托:BarcodeDelegate?var videoCaptureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)var device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)var 输出 = AVCaptureMetadataOutput()var previewLayer:AVCaptureVideoPreviewLayer?var captureSession = AVCaptureSession()变量代码:字符串?覆盖 func viewDidLoad() {super.viewDidLoad()self.view.backgroundColor = UIColor.clearself.setupCamera()}私人 func setupCamera() {让输入=尝试?AVCaptureDeviceInput(设备:videoCaptureDevice)如果 self.captureSession.canAddInput(input) {self.captureSession.addInput(输入)}self.previewLayer = AVCaptureVideoPreviewLayer(会话:captureSession)如果让 videoPreviewLayer = self.previewLayer {videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFillvideoPreviewLayer.frame = self.view.boundsview.layer.addSublayer(videoPreviewLayer)}让元数据输出 = AVCaptureMetadataOutput()如果 self.captureSession.canAddOutput(metadataOutput) {self.captureSession.addOutput(metadataOutput)metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]} 别的 {print("无法添加元数据输出")}}覆盖 func viewWillAppear(_ 动画:布尔){super.viewWillAppear(动画)if (captureSession.isRunning == false) {captureSession.startRunning();}}覆盖 func viewWillDisappear(_ 动画:布尔){super.viewWillDisappear(动画)if (captureSession.isRunning == true) {captureSession.stopRunning();}}func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {//这是读取代码时调用的委托方法对于 metadataObjects 中的元数据 {让 readableObject = metadata as!AVMetadataMachineReadableCodeObject让代码 = readableObject.stringValueself.dismiss(动画:true,完成:nil)self.delegate?.barcodeReaded(barcode: code!)打印(代码!)}}}

重点之一是在viewWillAppear(:)viewWillDisappear(:)中声明全局变量并启动和停止captureSession代码>方法.在您之前的代码中,我认为它根本没有被调用,因为它从未进入处理条形码的方法中.

希望对你有帮助.

I am following this tutorial and tried to convert codes form Swift 2.0 to 3.0. But when I launched the application, the app doesn't work! I mean, nothing happens! Here is my code:

ViewController:

class ViewController: UIViewController ,BarcodeDelegate {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        let barcodeViewController: BarcodeViewController = segue.destination as! BarcodeViewController
        barcodeViewController.delegate = self

    }



    func barcodeReaded(barcode: String) {
        codeTextView.text = barcode
        print(barcode)
    }

}

BarcodeVC:

import AVFoundation


protocol BarcodeDelegate {

    func barcodeReaded(barcode: String)
}

class BarcodeViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate {

    var delegate: BarcodeDelegate?
    var captureSession: AVCaptureSession!
    var code: String?


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        print("works")

        self.captureSession = AVCaptureSession();
        let videoCaptureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

        do {

            let videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)

            if self.captureSession.canAddInput(videoInput) {
                self.captureSession.addInput(videoInput)
            } else {
                print("Could not add video input")
            }

            let metadataOutput = AVCaptureMetadataOutput()
            if self.captureSession.canAddOutput(metadataOutput) {
                self.captureSession.addOutput(metadataOutput)

                metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
                metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code]
            } else {
                print("Could not add metadata output")
            }

            let previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
            previewLayer?.frame = self.view.layer.bounds
            self.view.layer .addSublayer(previewLayer!)
            self.captureSession.startRunning()
        } catch let error as NSError {
            print("Error while creating vide input device: (error.localizedDescription)")
        }



    }



    //I THINK THIS METHOD NOT CALL !
    private func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

        // This is the delegate'smethod that is called when a code is readed
        for metadata in metadataObjects {
            let readableObject = metadata as! AVMetadataMachineReadableCodeObject
            let code = readableObject.stringValue

            // If the code is not empty the code is ready and we call out delegate to pass the code.
            if  code!.isEmpty {
                print("is empty")

            }else {

                self.captureSession.stopRunning()
                self.dismiss(animated: true, completion: nil)
                self.delegate?.barcodeReaded(barcode: code!)


            }
        }

    }

Here is the output:

2016-09-17 18:10:26.000919 BarcodeScaning[2610:674253] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles 2016-09-17 18:10:26.007782 BarcodeScaning[2610:674253] [MC] Reading from public effective user settings.

解决方案

The first step needs to be declare access to any user private data types that is a new requirement in iOS 10. You can do it by adding a usage key to your app’s Info.plist together with a purpose string.

Because if you are using one of the following frameworks and fail to declare the usage your app will crash when it first makes the access:

Contacts, Calendar, Reminders, Photos, Bluetooth Sharing, Microphone, Camera, Location, Health, HomeKit, Media Library, Motion, CallKit, Speech Recognition, SiriKit, TV Provider.

To avoid the crash you need to add the suggested key to Info.plist:

And then the system shows the purpose string when asking the user to allow access:

For more information about it you can use this article:

I have done a little modifications to your BarcodeViewController to make it work properly as you can see below:

BarcodeViewController

import UIKit
import AVFoundation

protocol BarcodeDelegate {
   func barcodeReaded(barcode: String)
}

class BarcodeViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

   var delegate: BarcodeDelegate?

   var videoCaptureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
   var device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
   var output = AVCaptureMetadataOutput()
   var previewLayer: AVCaptureVideoPreviewLayer?

   var captureSession = AVCaptureSession()
   var code: String?

   override func viewDidLoad() {
      super.viewDidLoad()

      self.view.backgroundColor = UIColor.clear
      self.setupCamera()
   }

   private func setupCamera() {

      let input = try? AVCaptureDeviceInput(device: videoCaptureDevice)

      if self.captureSession.canAddInput(input) {
          self.captureSession.addInput(input)
      }

      self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

      if let videoPreviewLayer = self.previewLayer {
          videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
          videoPreviewLayer.frame = self.view.bounds
          view.layer.addSublayer(videoPreviewLayer)
      }

      let metadataOutput = AVCaptureMetadataOutput()
      if self.captureSession.canAddOutput(metadataOutput) {
          self.captureSession.addOutput(metadataOutput)

          metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
          metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]
      } else {
          print("Could not add metadata output")
      }
   }

   override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)

       if (captureSession.isRunning == false) {
          captureSession.startRunning();
       }
   }

   override func viewWillDisappear(_ animated: Bool) {
      super.viewWillDisappear(animated)

      if (captureSession.isRunning == true) {
         captureSession.stopRunning();
      }
   }

   func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
       // This is the delegate's method that is called when a code is read
       for metadata in metadataObjects {
           let readableObject = metadata as! AVMetadataMachineReadableCodeObject
           let code = readableObject.stringValue


           self.dismiss(animated: true, completion: nil)
           self.delegate?.barcodeReaded(barcode: code!)
           print(code!)
       }
   }
}

One of the important points was to declare the global variables and start and stop the captureSession inside the viewWillAppear(:) and viewWillDisappear(:) methods. In your previous code I think it was not called at all as it never enter inside the method to process the barcode.

I hope this help you.

这篇关于使用 AVFoundation 在 Swift 3.0 中扫描条码或二维码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆