

Swiftでバーコードリーダーを作成しており、カメラの起動は問題ないのですが、メタデータが取得できません。  
ビルドは成功しています。原因お分かりになりますでしょうか。  
よろしくお願いいたします。

[code]

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {
    
        // Connect as outlet
        @IBOutlet weak var previewView: UIView!
    
        // Make instance
        var captureSession = AVCaptureSession()
    
        // Make notification
        let notification = NotificationCenter.default
    
        // Status for privacy and in-output
        var authStatus:AuthorizedStatus = .authorized
        var inOutStatus:InputOutputStatus = .ready
    
        // Authorization Status
        enum AuthorizedStatus {
            case authorized
            case notAuthorized
            case failed
        }
        // InOut Status
        enum InputOutputStatus {
            case ready
            case notReady
            case failed
        }
    
        let x: CGFloat = 0.1
        let y: CGFloat = 0.4
        let width: CGFloat = 0.8
        let height: CGFloat = 0.2
    
        override func viewDidLoad(){
            super.viewDidLoad()
            // interrupt if processing session
            guard !captureSession.isRunning else {
                return
            }
            // privacy authorization for camera
            cameraAuth()
    
            // Set InputOutput
            setupInputOutput()
    
            // Check camera is ready
            if (authStatus == .authorized)&&(inOutStatus == .ready) {
                // Set previewLayer
                setPreviewLayer()
                // Start session
                captureSession.startRunning()
            } else {
                // alert
                showAlert(appName: "Camera")
            }
    
        }
    
        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 cameraAuth(){
            let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
            switch status {
            case .notDetermined:
                AVCaptureDevice.requestAccess(for: AVMediaType.video,
                                              completionHandler: { [unowned self] authorized in print("First Time", authorized.description)
                                                if authorized {
                                                    self.authStatus = .authorized
                                                } else {
                                                    self.authStatus = .notAuthorized
                                                }})
            case .restricted, .denied:
                authStatus = .notAuthorized
            case .authorized:
                authStatus = .authorized
            }
        }
    
        func setupInputOutput(){
            // Set resolution
            // captureSession.sessionPreset = AVCaptureSession.Preset.
    
            // Set input
            do {
                // Obtain devise
                let devise = AVCaptureDevice.default(
                    AVCaptureDevice.DeviceType.builtInWideAngleCamera,
                    for: AVMediaType.video,
                    position: AVCaptureDevice.Position.back
                )
    
                // where to input
                let input = try AVCaptureDeviceInput(device: devise!)
                if captureSession.canAddInput(input){
                    captureSession.addInput(input)
                } else {
                    print("Failed to add input to session")
                    return
                }
            } catch let err as NSError {
                print("Camera doesn't exist \(err)")
                return
            }
    
            // Set output
            let metadataOutput = AVCaptureMetadataOutput()
            if captureSession.canAddOutput(metadataOutput) {
                captureSession.addOutput(metadataOutput)
                metadataOutput.setMetadataObjectsDelegate((self as? AVCaptureMetadataOutputObjectsDelegate), queue: DispatchQueue.main)
                metadataOutput.metadataObjectTypes = [.ean13]
                metadataOutput.rectOfInterest = CGRect(x: y, y: 1 - x - width, width: height, height: width)
            } else {
                print("Failed to add output to session")
                return
            }
        }
    
        func setPreviewLayer(){
            // Make previewLayer
            let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            previewLayer.frame = view.layer.bounds
            previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect
    
            // Add preview
            previewView.layer.addSublayer(previewLayer)
    
            // Add red-frame
        //        let detectionArea = UIView()
        //        detectionArea.frame = CGRect(x: view.frame.size.width * x, y: view.frame.size.height * y, width: view.frame.size.width * width, height: view.frame.size.height * height)
        //        detectionArea.layer.borderColor = UIColor.red.cgColor
        //        detectionArea.layer.borderWidth = 3
        //        view.addSubview(detectionArea)
        }
    
        func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection){
            for metadata in metadataObjects as! [AVMetadataMachineReadableCodeObject] {
                // check whether it's barcode
                if metadata.type == AVMetadataObject.ObjectType.ean13 {
                    if metadata.stringValue != nil {
                        print(metadata.stringValue!)
                    }
                }
                print("metadataOutput called")
    
                // metadata
                print(metadata.type)
                print(metadata.stringValue!)
            }
        }
    
        func showAlert(appName: String){
            let aTitle = "privacy authorization for " + appName
            let aMessage = "Please authorize by Setting>Privacy> " + appName
            let alert = UIAlertController(title: aTitle, message: aMessage, preferredStyle: .alert)
    
            // OK(nothing)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    
            // Open Setting
            alert.addAction(UIAlertAction(title: "Open Setting", style: .default, handler: { action in UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)}))
    
            // Display alert
            self.present(alert, animated: false, completion: nil)
        }
    }
    
[/code]


CC BY-SA 4.0
2019-01-05T02:05:48.750
51713
2020-09-18T13:06:00.597
2020-07-19T16:45:18.820
3060
31671
question
swift swift4
Swift 4 バーコードリーダアプリのメタデータ取得について


全部のコードをチェックできたわけではないのですが、少なくともここは直さないと動かないというのがあるのでそこだけ示させていただきます。

**ダメ** な部分:

[code]

            metadataOutput.setMetadataObjectsDelegate((self as? AVCaptureMetadataOutputObjectsDelegate), queue: DispatchQueue.main)
    
[/code]

delegateを設定する際に型に関するエラーが出た場合、`as?`でキャストしても、殆どの場合、期待される動作にはなりません。ちゃんと設定するインスタンスのクラス(今の場合`ViewController`)を必要なプロトコル(`AVCaptureMetadataOutputObjectsDelegate`)に適合させてください。

クラスヘッダには`AVCaptureMetadataOutputObjectsDelegate`を追加:

[code]

    class ViewController: UIViewController, AVCapturePhotoCaptureDelegate,
        AVCaptureMetadataOutputObjectsDelegate {
    
[/code]

(`AVCapturePhotoCaptureDelegate`が必要かどうかわかりませんでしたが、とりあえずそのままにしておきました。)

delegateを設定する場合には、キャストはしない:

[code]

            metadataOutput.setMetadataObjectsDelegate(self, queue: .main)
    
[/code]

* * *

本題には関係ありませんが、`cameraAuth()`の中で`unowned`を使っておられますが、`unowned`と`weak`の違い、どんな場合にそれらが必要になるかを十分理解しておられないのではないでしょうか。あなたのコードの場合、`unowned`も`weak`も必要ありません。十分理解できないまま「念のため」で付けるなら`[unowned
self]`ではなく`[weak
self]`を使用しておくことをお勧めします。(もちろんそれによりOptionalとしての取り扱いが必要。)`unowned`は使い方を間違えると簡単にクラッシュの原因になります。


CC BY-SA 4.0
2019-01-05T02:40:59.083
51714
2019-01-05T02:40:59.083
13972
51713
answer