2016-06-03 3 views
0

카메라 세션을 설정할 때 Crashlytics에 이상한 충돌이 표시됩니다. stacktrace는 addInput 메소드에서 크래시가 발생했음을 보여줍니다.AVCaptureDeviceInput을 추가 할 때 AVCaptureSession에 충돌이 발생했습니다.

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 
     } 
    } 
} 

setupCamSession가있는 viewDidLoad에서 호출 viewWillAppear에서 runSession와 나는 또한 viewWillDisappear에서 stopSession 방법이있다. 카메라 세션과 관련된 모든 것이 백그라운드 직렬 대기열에 전달됩니다.

충돌이 100 % 발생하지 않으며 사용하는 장치에서 크래시를 재현 할 수 없습니다. 감사합니다. This is a screenshot of the stacktrace

+0

보기로 이동하십시오. 적용 또는 표시합니다 .DidAppear –

+0

왜? 나는 그것을 viewDidLoad()에 유지하는 것을 선호한다. 실제로 홈 화면에는 카메라보기가 있으며 홈 화면에서 여러 번보기 컨트롤러를 밀고 팝합니다. ViewWillAppear은 여러 번 호출되며 카메라 세션을 다시 설정할 때마다 호출됩니다. 현재는 카메라 세션 만 실행 중입니다. – ELKA

+0

https://developer.apple.com/library/ios/samplecode/AVCam/Listings/AVCam_AAPLCameraViewController_m.html#//apple_ref/doc/uid/DTS40010112-AVCam_AAPLCameraViewController_m-DontLinkElementID_6에서 영감을 받았습니다. 그들은 viewDidLoad()에서 입력을 설정합니다. – ELKA

답변

1

deinit에서 옵저버를 제거했는지 확인하십시오. 이 문제는 카메라 캡쳐 화면으로 돌아갈 때 발생하며, adjustingFocus에 대한 관찰자를 제거하지 않은 것을 보았습니다. 내가 그것을 제거 했더라면 deinit는 전부 건강했다.

+0

내 질문을 편집하고 stopCaptureSession() 메서드를 추가했습니다. 이 방법은 adjustmentFocus를 위해 관찰자를 제거하고있었습니다. 로그에는 관측통이 제거 된 후 초심자가 호출되었다고되어 있습니다. – ELKA

+0

videoDeviceInput.device가 nil이되는 방식이나 다른 방식으로 가능합니까? 이것이 발생하면'self.videoDeviceInput? .device? .removeObserver (self, forKeyPath : "adjustingFocus", 컨텍스트 : nil)'이 호출되지 않습니다. – ELKA

관련 문제