2016-06-03 5 views
0

Ich habe einen seltsamen Absturz bei Crashlytics beim Einrichten einer Kamera-Sitzung. Der Stacktrace zeigt, dass der Absturz bei der Methode addInput aufgetreten ist.Absturz in AVCaptureSession beim Hinzufügen eines AVCaptureDeviceInput

func setupCamSession(){ 
    self.captureSession = AVCaptureSession() 
    self.cameraView.setSession(self.captureSession) 
    self.sessionQueue = dispatch_queue_create("com.myapp.camera_queue", DISPATCH_QUEUE_SERIAL) 
    self.setupResult = .Success 
    switch AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo){ 
    case .Authorized: 
     break //already we set it to success 
    case .NotDetermined: 
     // The user has not yet been presented with the option to grant video access. 
     // We suspend the session queue to delay session setup until the access request has completed 
     dispatch_suspend(self.sessionQueue) 
     AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted) -> Void in 
      if (!granted) { 
       self.setupResult = .CameraNotAuthorized 
      } 
      dispatch_resume(self.sessionQueue) 
     }) 
    default: 
     self.setupResult = .CameraNotAuthorized 
    } 

    dispatch_async(self.sessionQueue){ 
     if self.setupResult != .Success{ 
      return 
     } 
     //link input to captureSession 
     guard let videoDevice = self.deviceWithMediaType(AVMediaTypeVideo, position: AVCaptureDevicePosition.Back) else{ 
      AppLog("Video Device Unavailable") 
      self.setupResult = .SessionConfigurationFailed 
      return 
     } 
     var videoDeviceInput: AVCaptureDeviceInput! 
     do { 
      videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) 
     }catch { 
      AppLog("Could not create video device input") 
     } 

     ///////////////////////////////////////////////////// 
     self.captureSession.beginConfiguration() 

     if self.captureSession.canAddInput(videoDeviceInput){ 
      self.captureSession.addInput(videoDeviceInput) 
      self.videoDeviceInput = videoDeviceInput 
      self.videoDevice = videoDevice 
      dispatch_async(dispatch_get_main_queue()){ 
       //update the cameraView layer on the main thread 
       let previewLayer : AVCaptureVideoPreviewLayer = self.cameraView.layer as! AVCaptureVideoPreviewLayer 
       previewLayer.connection.videoOrientation = AVCaptureVideoOrientation(ui:UIApplication.sharedApplication().statusBarOrientation) 
      } 
     }else{ 
      AppLog("Could not add video device input to the session") 
      self.setupResult = .SessionConfigurationFailed 
     } 

     //link output to captureSession 
     let stillImageOutput = AVCaptureStillImageOutput() 
     if self.captureSession.canAddOutput(stillImageOutput){ 
      self.captureSession.addOutput(stillImageOutput) 
      self.stillImageOutput = stillImageOutput 
      stillImageOutput.outputSettings = [AVVideoCodecKey : AVVideoCodecJPEG] 
     }else{ 
      AppLog("Could not add still image output to the session") 
      self.setupResult = .SessionConfigurationFailed 
     } 

     self.captureSession.commitConfiguration() 
     ///////////////////////////////////////////////////// 
    } 
} 

func runSession(){ 
    dispatch_async(self.sessionQueue){ 
     switch self.setupResult!{ 
     case .Success: 
      self.videoDeviceInput!.device.addObserver(self, forKeyPath: "adjustingFocus", options: NSKeyValueObservingOptions.New, context: nil) 
      self.captureSession.addObserver(self, forKeyPath: "running", options: [.New], context: &SessionRunningContext) 
      self.captureSession.startRunning() 
      self.captureSessionRunning = self.captureSession.running 
      if !self.captureSessionRunning { 
       self.captureSession.removeObserver(self, forKeyPath: "running", context: &SessionRunningContext) 
       self.videoDeviceInput?.device?.removeObserver(self, forKeyPath: "adjustingFocus", context: nil) 
      } 
     default: 
     //Handle errors. 
     } 
    } 
func stopCaptureSession(){ 
    dispatch_async(self.sessionQueue){ 
     if self.setupResult == .Success{ 
      if self.captureSessionRunning{ 
       self.captureSession.stopRunning() 
       self.videoDeviceInput?.device?.removeObserver(self, forKeyPath: "adjustingFocus", context: nil) 
       self.captureSession.removeObserver(self, forKeyPath: "running", context: &SessionRunningContext) 
      } 
      self.captureSessionRunning = false 
     } 
    } 
} 

Die setupCamSession in viewDidLoad, die runSession in viewWillAppear genannt und ich habe auch eine stopSession Methode in viewWillDisappear. Alles, was mit der Kamerasitzung zusammenhängt, wird in einer seriellen Warteschlange im Hintergrund ausgelöst.

Der Absturz passiert nicht 100% der Zeit und ich kann den Absturz nicht auf dem Gerät reproduzieren, das ich benutze. Danke This is a screenshot of the stacktrace

+0

move it zu viewWillAppear oder viewDidAppear –

+0

Warum? Ich bevorzuge es in viewDidLoad() zu halten. In der Tat hat der Home-Bildschirm die Kamera-Ansicht und wir schieben und knallen View-Controller viele Male auf dem Home-Bildschirm. So wird ViewWillAppear mehrmals aufgerufen und jedes Mal wird die Kamera-Session neu eingerichtet. Derzeit wird nur die Kamerasitzung ausgeführt. – ELKA

+0

Ich wurde von https://developer.apple.com/library/ios/samplecode/AVCam/Listings/AVCam_AAPLCameraViewController_m.html#//apple_ref/doc/uid/DTS40010112-AVCam_AAPLCameraViewController_m-DontLinkElementID_6 inspiriert. Sie konfigurieren die Eingabe in viewDidLoad() – ELKA

Antwort

1

Stellen Sie sicher, dass Sie Beobachter auf deinit entfernen. Ich habe gesehen, dass das passiert, wenn ich zum Kamera-Aufnahmebildschirm zurückgekehrt bin und den Beobachter für adjustingFocus nicht entfernt habe. Sobald ich das in deinit entfernte, war alles gut.

+0

Ich habe meine Frage bearbeitet und die Methode stopCaptureSession() hinzugefügt. Diese Methode entfernte den Beobachter zum Anpassen von Fokus. Die Protokolle sagen, dass die Beobachter entfernt wurden, dann wurde das Deinit aufgerufen. – ELKA

+0

Ist es auf die eine oder andere Weise möglich, dass videoDeviceInput.device null wird? Wenn dies geschieht '' self.videoDeviceInput? .device? .removeObserver (self, forKeyPath: "justingFocus", Kontext: nil) 'wird nicht aufgerufen. – ELKA