14970


下記ページを参考に２次元バーコード読み取りをswift2で書いたのですが、実機デバック時にコンソール画面の「fatal error:
unexpectedly found nil while unwrapping an Optional
value」と言うエラーが出てきます。どこをoptional型にすればいいのでしょうか？xcode7beta5を使用しています。

追記  
他のサイトなどを参考にコードを変更してみました。そしたら実機で起動するが真っ白な画面となりカメラが起動しません。コードの修正をお願いします。

[<http://swift-salaryman.com/avmetadataobject.php> ][1]

[code]

    import UIKit
    import AVFoundation
    
    
    class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    
    let session         : AVCaptureSession! = AVCaptureSession()
    var previewLayer    : AVCaptureVideoPreviewLayer!
    var highlightView   : UIView = UIView()
    // デバイス.
    var captureDevice : AVCaptureDevice!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view, typically from a nib.
        session.sessionPreset = AVCaptureSessionPresetLow
    
        // Allow the view to resize freely
        self.highlightView.autoresizingMask =   [UIViewAutoresizing.FlexibleTopMargin, UIViewAutoresizing.FlexibleBottomMargin, UIViewAutoresizing.FlexibleLeftMargin, UIViewAutoresizing.FlexibleRightMargin]
    
        // Select the color you want for the completed scan reticle
        self.highlightView.layer.borderColor = UIColor.greenColor().CGColor
        self.highlightView.layer.borderWidth = 3
    
        // Add it to our controller's view as a subview.
        self.view.addSubview(self.highlightView)
    
    
        // デバイス一覧の取得.
        let devices = AVCaptureDevice.devices()
    
        // バックカメラをcaptureDeviceに格納.
        for device in devices{
            if(device.position == AVCaptureDevicePosition.Back){
                captureDevice = device as! AVCaptureDevice
                if captureDevice != nil {
                    print("Capture device found")
                }
            }
        }
    
        do {
             captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
            let input = try AVCaptureDeviceInput(device: captureDevice)
            // Do the rest of your work...
        } catch let error as NSError {
            // Handle any errors
            print(error)
        }
        // If our input is not nil then add it to the session, otherwise we're kind of done!
    
    
        let output = AVCaptureMetadataOutput()
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        session.addOutput(output)
        output.metadataObjectTypes = output.availableMetadataObjectTypes
    
    
        previewLayer = AVCaptureVideoPreviewLayer(session: session)
        self.view.layer.addSublayer(previewLayer)
        previewLayer?.frame = self.view.layer.frame
        // Start the scanner. You'll have to end it yourself later.
        session.startRunning()
    
    }
    
    // This is called when we find a known barcode type with the camera.
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
    
        var highlightViewRect = CGRectZero
    
        var barCodeObject : AVMetadataObject!
    
        var detectionString : String!
    
        let barCodeTypes = [AVMetadataObjectTypeUPCECode,
            AVMetadataObjectTypeCode39Code,
            AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code,
            AVMetadataObjectTypeEAN8Code,
            AVMetadataObjectTypeCode93Code,
            AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeQRCode,
            AVMetadataObjectTypeAztecCode
        ]
    
    
        // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
        for metadata in metadataObjects {
    
            for barcodeType in barCodeTypes {
    
                if metadata.type == barcodeType {
                    barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)
    
                    highlightViewRect = barCodeObject.bounds
    
                    detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue
    
                    self.session.stopRunning()
                    break
                }
    
            }
        }
    
        print(detectionString)
        self.highlightView.frame = highlightViewRect
        self.view.bringSubviewToFront(self.highlightView)
    
     }
    }
    
[/code]


CC BY-SA 3.0
2015-08-28T13:41:26.953
14968
2015-08-28T17:04:24.327
2015-08-28T17:04:24.327
11113
11113
question
ios swift xcode
下記ページを参考に２次元バーコード読み取りをswift2で書いたのですが、実機デバック時にコンソール画面の「fatal error: unexpectedly found nil while unwrapping an Optional value」と言うエラーが出てきます。


ビデオキャプチャの処理にも問題があるのですが（キャプチャセッションに入力を渡していない、アプリがカメラへアクセスする権限を持っていない場合を想定していないなど）、表題のエラーがなぜ起きるのかをもって回答とします。

この場合、エラーとなる箇所は、

[code]

    previewLayer = AVCaptureVideoPreviewLayer(layer: session) as AVCaptureVideoPreviewLayer
    previewLayer.frame = self.view.bounds
    
[/code]

`self.view.bounds`をセットする箇所です。それがなぜかというと、

[code]

    var previewLayer: AVCaptureVideoPreviewLayer!
    
[/code]

`previewLayer`をImplicitly Unwrapped Optionalで宣言しているためです。

「どこをoptional型にすればいいのでしょうか？」という質問は逆で、Implicitly Unwrapped
Optional型として宣言されているがゆえに、`previewLayer`が`nil`の状態でアクセスしたため、実行時エラーになっているのです。

`AVCaptureVideoPreviewLayer`の`init`の宣言を読むと、

[code]

    class AVCaptureVideoPreviewLayer : CALayer {
        init!(session: AVCaptureSession!)
    }
    
[/code]

`init!()`となっています。この`!`が付いているイニシャライザはFailable
Initializersと呼び、生成に失敗した場合に`nil`を返却する可能性があることを示しています。実際に上記コードでは`nil`が返却されています。

* * *

まとめると、

  1. `AVCaptureSession`が適切な状態でないため、`AVCaptureVideoPreviewLayer`の生成に失敗
  2. `nil`の状態の`previewLayer`にアクセスしたため、暗黙のunwrapによって実行時エラー

です。Failable Initializersで生成するときには、`nil`チェックを行いましょう。


CC BY-SA 3.0
2015-08-28T14:21:04.717
14970
2015-08-28T14:45:36.753
2015-08-28T14:45:36.753
5337
5337
14968
answer