1

I have a ViewController that continuously scans for QR codes and implements AVCaptureMetadataOutputObjectsDelegate to retrieve the metadata output.

class ScanViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    var captureSession = AVCaptureSession()
    var videoPreviewLayer: AVCaptureVideoPreviewLayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Get the back-facing camera for capturing videos
        let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera], mediaType: AVMediaTypeVideo, position: .back)

        guard let captureDevice = deviceDiscoverySession?.devices.first else {
            print("Failed to get the camera device")
            return
        }

        do {
            // Get an instance of the AVCaptureDeviceInput class using the previous device object.
            let input = try AVCaptureDeviceInput(device: captureDevice)

            // Set the input device on the capture session.
            captureSession.addInput(input)

            // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
            let captureMetadataOutput = AVCaptureMetadataOutput()
            captureSession.addOutput(captureMetadataOutput)

            // Set delegate and use the default dispatch queue to execute the call back
            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]

        } catch {
            // If any error occurs, simply print it out and don't continue any more.
            print(error)
            return
        }

        // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoPreviewLayer?.frame = view.layer.bounds
        view.layer.addSublayer(videoPreviewLayer!)

        // Start video capture.
        captureSession.startRunning()
    }

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        print("in function of extension")
        // Check if the metadataObjects array is not nil and it contains at least one object.
        if metadataObjects.count == 0 {
            print("nada qr code")
            return
        }

        // Get the metadata object.
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

        if metadataObj.type == AVMetadataObjectTypeQRCode {
            if metadataObj.stringValue != nil {
                print(metadataObj.stringValue)
            }
        }
    }
}

But for some reason the delegate callback doesn't get called. In the tutorial I'm following, it runs perfectly.

Hopefully someone can provide any words of assistance. Anything would be immensely helpful to get me on the right track. Thanks so much in advance.

Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
Theo Strauss
  • 1,281
  • 3
  • 19
  • 32

3 Answers3

1

The reason for not running is that metadataOutput(...) is technically a built-in function of the AV framework, but only for Swift 4. In Swift 3.0 and 3.2, the correct function is:

captureOutput(_ output: _AVCaptureOutput!, didOutputMetadataObjects: [Any]!, from connection: AVCaptureConnection!)  

That should run!

Theo Strauss
  • 1,281
  • 3
  • 19
  • 32
0

The extension code you posted does not compile for me. I had to add public to the method declaration:

public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {

I am using Swift 4.

Xcoder
  • 1,433
  • 3
  • 17
  • 37
Rafał Sroka
  • 39,540
  • 23
  • 113
  • 143
0

Change the code as follows. It may work, at least it worked for me. I am using Swift 4.2

captureMetadataOutput.metadataObjectTypes = captureDeviceOutput.availableMetadataObjectTypes
Martin
  • 846
  • 1
  • 9
  • 23