2017-04-17 77 views
-1

此視圖控制器正從另一個故事板上的按鈕調用。我每次點擊按鈕,我得到爲什麼previewLayer在我嘗試獲取邊界時返回nil?

fatal error: unexpectedly found nil while unwrapping an Optional value 2017-04-16 21:00:39.929042 FaceOnACase[757:377279] fatal error: unexpectedly found nil while unwrapping an Optional value

上線self.previewLayer?.frame = self.previewView.bounds。

我以前在單獨的單一視圖應用程序中工作時使用了此代碼,但是當我將代碼轉移並連接IBOutlets時,出於某種原因無法使其工作。

我找不到類似的問題,我不確定如何解決此問題。任何幫助表示讚賞,謝謝。

import UIKit 
import AVFoundation 

class CaptureController: UIViewController, AVCapturePhotoCaptureDelegate { 
    var captureSesssion: AVCaptureSession! 
    var cameraOutput: AVCapturePhotoOutput! 
    var previewLayer: AVCaptureVideoPreviewLayer! 
    @IBOutlet weak var capturedImage: UIImageView! 
    @IBOutlet weak var previewView: UIView! 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     captureSesssion = AVCaptureSession() 
     captureSesssion.sessionPreset = AVCaptureSessionPresetPhoto 
     cameraOutput = AVCapturePhotoOutput() 
     let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) 
     do { 
      let input = try AVCaptureDeviceInput(device: device) 
      if (captureSesssion.canAddInput(input)) { 
       captureSesssion.addInput(input) 
       if (captureSesssion.canAddOutput(cameraOutput)) { 
        captureSesssion.addOutput(cameraOutput) 
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion) 
        self.previewLayer?.frame = self.previewView.bounds 
        previewView.layer.addSublayer(previewLayer) 
        captureSesssion.startRunning() 
       } 
      } else { 
       print("issue here : captureSesssion.canAddInput") 
      } 
     } catch let error { 
      print("error \(error.localizedDescription)") 
     } 
    } 
    // Take picture button 
    @IBAction func didPressTakePhoto(_ sender: UIButton) { 
     let settings = AVCapturePhotoSettings() 
     let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first! 
     let previewFormat = [ 
      kCVPixelBufferPixelFormatTypeKey as String: previewPixelType, 
      kCVPixelBufferWidthKey as String: 160, 
      kCVPixelBufferHeightKey as String: 160 
     ] 
     settings.previewPhotoFormat = previewFormat 
     cameraOutput.capturePhoto(with: settings, delegate: self) 
    } 
    // callBack from take picture 
    func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { 
     if let error = error { 
      print("error occured : \(error.localizedDescription)") 
     } 
     if let sampleBuffer = photoSampleBuffer, 
      let previewBuffer = previewPhotoSampleBuffer, 
      let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) { 
      print(UIImage(data: dataImage)?.size as Any) 
      let dataProvider = CGDataProvider(data: dataImage as CFData) 
      let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent) 
      let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right) 
      self.capturedImage.image = image 
     } else { 
      print("some error here") 
     } 
    } 
    // This method you can use somewhere you need to know camera permission state 
    func askPermission() { 
     print("here") 
     let cameraPermissionStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) 
     switch cameraPermissionStatus { 
     case .authorized: 
      print("Already Authorized") 
     case .denied: 
      print("denied") 
      let alert = UIAlertController(title: "Sorry :(" , message: "But could you please grant permission for camera within device settings", preferredStyle: .alert) 
      let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil) 
      alert.addAction(action) 
      present(alert, animated: true, completion: nil) 
     case .restricted: 
      print("restricted") 
     default: 
      AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { 
       [weak self] 
       (granted :Bool) -> Void in 
       if granted == true { 
        // User granted 
        print("User granted") 
        DispatchQueue.main.async(){ 
         //Do smth that you need in main thread 
        } 
       } 
       else { 
        // User Rejected 
        print("User Rejected") 
        DispatchQueue.main.async(){ 
         let alert = UIAlertController(title: "WHY?" , message: "Camera it is the main feature of our application", preferredStyle: .alert) 
         let action = UIAlertAction(title: "Ok", style: .cancel, handler: nil) 
         alert.addAction(action) 
         self?.present(alert, animated: true, completion: nil) 
        } 
       } 
      }) 
     } 
    } 
} 

回答

2

previewLayer返回nil。它是previewViewnil。確保你已經正確地將它連接到故事板上的插座。

另外你在做什麼還爲時過早。您無法在viewDidLoad開始捕獲會話。請記住,這意味着視圖存在,但它甚至不在界面中!您至少需要一個接口才能啓動捕獲會話。

+0

好的,我檢查了一下,我把它連接好了。現在,我應該把它們放在viewWillAppear而不是viewDidLoad中嗎? – David

+0

因爲現在一切似乎都正常。謝謝btw! – David

+0

我會建議使用'viewDidLayoutSubviews',因爲你依賴'self.previewView.bounds',直到那時它纔會正確設置。您將需要一個Bool標誌,以便您的代碼只運行一次(因爲viewDidLayoutSubviews被多次調用)。 – matt

相關問題