2

There seems to be a lot of issues similar to what I am experiencing:

AVmetadata changes with swift 4 xcode 9

AVCaptureMetadataOutput setMetadataObjectTypes unsupported type found

And there is an Apple bug that deals with AVFoundation:

https://forums.developer.apple.com/thread/86810#259270

But none of those seem to actually be the answer for me.
I have code that runs great in swift 3, but will only error out in swift 4. Using the solutions in the above links results in no change at all.

Code:

import UIKit
import AVFoundation

class BarCodeScanViewController: UIViewController,     AVCaptureMetadataOutputObjectsDelegate {
weak var delegate: FlowControllerDelegate?

var captureSession: AVCaptureSession = AVCaptureSession()
var previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer()


override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = UIColor.black
    captureSession = AVCaptureSession()

    guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
    let videoInput: AVCaptureDeviceInput

    do {
        videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
    } catch {
        return
    }

    if (captureSession.canAddInput(videoInput)) {
        captureSession.canAddInput(videoInput)
    } else {
        failed()

        return
    }

    // let captureMetadataOutput = AVCaptureMetadataOutput()
    let metadataOutput = AVCaptureMetadataOutput()

    if captureSession.canAddOutput(metadataOutput) {
        captureSession.addOutput(metadataOutput)

        // Check status of camera permissions
        metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
//            metadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.upce]
        metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417, .upce]
    } else {
        failed()

        return
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.frame = view.layer.bounds
    previewLayer.videoGravity = .resizeAspectFill
    view.layer.addSublayer(previewLayer)

    captureSession.startRunning()
}

func failed() {
    let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
    ac.addAction(UIAlertAction(title: "OK", style: .default))

    present(ac, animated: true)

//        captureSession = nil
}

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

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

override func viewWillDisappear(_ animated: Bool) {
    if captureSession.isRunning == true {
        captureSession.stopRunning()
    }

    super.viewWillDisappear(animated)
}

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
    captureSession.stopRunning()

    if let metatdataObject = metadataObjects.first {
        guard let readableObject = metatdataObject as? AVMetadataMachineReadableCodeObject else { return }
        guard let stringValue = readableObject.stringValue else { return }
        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        found(code: stringValue)
    }

    dismiss(animated: true)
}

func found(code: String) {
    print(code)
}

override var prefersStatusBarHidden: Bool {
    return true
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask     {
    return .portrait
}
}

When I build this code in Xcode 8 and swift 3 it works fine. When I run it in Xcode 9 swift 4it crashes at adding the media types:

metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417, .upce]

In both cases I am building to an iOS 11 device that did not have the beta on it previously.

I have tried the "__" to see if it was the Apple bug metioned above. If I comment the line out the code runs but there is not capture.

Is there some other bug Apple introduced maybe? Anyone else having this issue?

Any help would be appreciated.

Thanks

addzo
  • 845
  • 3
  • 13
  • 37

1 Answers1

11

Further information for Clarity:

Leevi Graham is correct as well as it being true that Apple changed the stack without proper documentation. This results in it seeming like there is a bug.

Barcode on swift 4

Clarifying comments that helped me:

The delegate call back has changed from:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)

to

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

HOWEVER, the real problem I was having was that you no longer set a long array of types to get your metadataObjectTypes. You now just set for all available types:

metadataOutput.metadataObjectTypes = 
metadataOutput.availableMetadataObjectTypes

So ...

This is, in fact an API issue. Several radar issues were filed for it. But Apple has Kindly changed their AVFoundation docs to address the issue.

anka
  • 3,817
  • 1
  • 30
  • 36
addzo
  • 845
  • 3
  • 13
  • 37