2017-03-06 3 views
0

私は、コールバック用のデリゲートスタイルのインターフェイスを持つ、基本viewControllerでラップされたカメラで作業しているので、クライアントとして行う必要があります。カメラビューコントローラ、デリゲートメソッドを実装し、UIボタンを追加します。 私の質問は、ビデオを録画することです。独自のバックグラウンドタスクでビデオ録画が開始され、録画を一時ファイルに書き込むことができます。デリゲートコールバックを別のキューからメインキューにディスパッチAVFoundation

public func startRecording() 
{ 
    guard let movieFileOutput = self.movieFileOutput else { return } 

    //get video preview layer's video orientation on main queue 
    guard let videoPreviewLayerOrientation = self.previewView.videoPreviewLayer?.connection.videoOrientation else { 
     print("handleRecord: videoPreviewLayer is nil") 
     return 
    } 

    self.sessionQueue.async { 

     if !movieFileOutput.isRecording { 
      if UIDevice.current.isMultitaskingSupported { 

       self.backgroundRecordingID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil) 
     } 

     //update orientation on the movie file output video connection before recording 
     let movieFileOutputConnection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo) 
      movieFileOutputConnection?.videoOrientation = videoPreviewLayerOrientation 

     //start recording to a temporary file: 
     let outputFileName = UUID().uuidString 
     let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!) 
      movieFileOutput.startRecording(toOutputFileURL: URL(fileURLWithPath: outputFilePath), recordingDelegate: self) 
     } 
    } 
} 

ので、記録がself.sessionQueueに派遣バックグラウンドタスクとして設定され:これは私の private let sessionQueue = DispatchQueue(label: "com.andrewferrarone.sessionQueue")セッションキュー上で行われます。録音を停止すると、私はAVCaptureFileOutputRecordingDelegateメソッドを受け取ります。このメソッドでは、ファイルパスを使用して代理人をコールバックし、次にクリーンアップしたいと考えています。クリーンアップが発生して一時ファイルが削除される前に、デリゲートがテンポラリファイルパスから録音を保持できることを確認するにはどうすればよいですか?

public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) 
{ 
    //cleanup func for later 
    func cleanup() 
    { 
     let path = outputFileURL.path 

     if FileManager.default.fileExists(atPath: path) { 
      do { 
       try FileManager.default.removeItem(atPath: path) 
      } 
      catch let error { 
       print("Could not remove file at url: \(outputFileURL), error: \(error.localizedDescription)") 
      } 
     } 

     if let currentBackgroundRecordingID = self.backgroundRecordingID { 
      self.backgroundRecordingID = UIBackgroundTaskInvalid 

      if currentBackgroundRecordingID != UIBackgroundTaskInvalid { 
       UIApplication.shared.endBackgroundTask(currentBackgroundRecordingID) 
      } 
     } 
    } 

    var success = true 

    if error != nil { 
     print("Movie file finishing error: \(error)") 
     success = ((error as NSError).userInfo[AVErrorRecordingSuccessfullyFinishedKey] as AnyObject).boolValue 
    } 

    DispatchQueue.main.async { 
     self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success) 
    } 

    cleanup() 
} 

は、だから私は戻って結果をメインキューの私のデリゲートを呼び出したが、私は右の私のデリゲートを呼び出した後に戻ってメインキューにこれを行う必要があり、私はcleanup()をコールする必要がありますか?これは安全ですか?または私がそれを今のままにしておけば、self.sessionQueueにあり、デリゲートメソッドの実装にレコーディングを持続させる時間がある前にcleanup()が起こるかどうかはわかりません。誰が私に何が起こっているのか、そしてここでやるのが一番安全なことについていくらかの洞察を与えることができれば、それは素晴らしいことです。 Appleによると、ドキュメントには、特定のスレッドでAVCaptureFileOutputRecordingDelegate didFinishRecordingToOutputFileAtメソッドが呼び出されているとは限りません。あなたの時間と助けてくれてありがとう!私はそれがこのような状況を処理する標準的な方法になると思います

DispatchQueue.main.async { 
    self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success) 
    self.sessionQueue.async { 
     cleanup() 
    } 
} 

:どの程度

答えて

1

。デリゲートメソッドが終了すると、そのデリゲートがファイルで完了した(または他の場所にコピーされた)とみなされます。

関連する問題