オリジナル情報源
概要
iOSデバイスのカメラで写真をキャプチャすることは、物理的なカメラメカニズム、画像信号処理、オペレーティングシステム、アプリを含む複雑なプロセスです。アプリがこのプロセスの多くの段階を無視して単純に最終結果を待つことは可能ですが、各ステップを監視することで、より応答性の高いカメラインターフェイスを作成できます。
capturePhoto(with:delegate:)
を呼び出した後、デリゲートオブジェクトはプロセスの5つの主要なステップ(写真の設定によってはそれ以上)に沿って進むことができます。作成するキャプチャワークフローとキャプチャUIに応じて、デリゲートは次の手順の一部またはすべてを処理できます。
- 設定完了
- 露出開始
- 露出完了
- 結果データ配信
- キャプチャ完了
キャプチャシステムは、このプロセスの各ステップでAVCaptureResolvedPhotoSettings
オブジェクトを提供します。同時に複数のキャプチャが進行している可能性があるため、解決された各写真設定オブジェクトには、写真の撮影に使用したAVCapturePhotoSettings
のuniqueID
と一致するuniqueID
値を持つ
キャプチャ設定を取得する
写真の設定を指定する場合、選択する設定の一部は自動であり、キャプチャシステムがキャプチャの瞬間に正確に決定するために残されます。たとえば、AVCaptureDevice.FlashMode.auto
フラッシュモードを選択すると、カメラ自体がシーンの照明に基づいて、写真を露光するときにフラッシュを発光するかどうかを決定できます。
露光を開始する直前に、写真出力はデリゲートのメソッドを呼び出します。そのメソッドのパラメーターは、キャプチャの実際の設定を示します。たとえば、フラッシュモードを選択した場合、解決された設定オブジェクトは、現在のキャプチャでフラッシュが使用されているかどうかを通知します。この情報を使用して、UIでフラッシュが使用されたことを示すことができます。resolvedSettings
AVCaptureDevice.FlashMode.auto
露出開始の処理
露出時間が始まると、写真出力はデリゲートのphotoOutput(_:willBeginCaptureFor:)
メソッドを呼び出します。従来の写真では、この瞬間はカメラのシャッターが開くことに相当します。このとき、シャッター音も自動的に鳴ります。
UIでこのメソッドに応答して、要求された写真が撮影されていることを示すシャッターアニメーションまたはその他のインジケーターを表示できます。
露出終了の処理
写真の出力は、露出時間が完了するとすぐにデリゲートのphotoOutput(_:didCapturePhotoFor:)
メソッドを呼び出します。アプリに画像を提供する前に、システムはまだカメラデータを処理する時間を必要としますが、この瞬間を使用して、UIに露出が完了したことを表示できます。たとえば、メソッドでカメラのプレビューを非表示にし、willCapturePhotodidCapturePhotoメソッドでもう一度表示することで、シャッター効果をシミュレートできます。
写真結果の処理
写真出力にアプリで利用できる画像データがある場合、デリゲートのphotoOutput(_:didFinishProcessingPhoto:error:)
メソッドを呼び出します。写真の設定によっては、写真の出力でこのメソッドが複数回呼び出される場合があります。
- ブラケットキャプチャを要求した場合、このメソッドはブラケット内の露出ごとに(少なくとも)1回起動し、その露出の画像を提供します。
- RAW形式と処理済み形式(HEIF / HEVCやJPEGなど)の両方でのキャプチャを要求した場合、このメソッドは(少なくとも)各形式に対して1回発生します。
たとえば、3つの露出ブラケットでRAW + HEIFキャプチャを要求すると、写真出力はデリゲートのdidFinishProcessingPhotoメソッドを6回呼び出し(2つのフォーマット×3つの露出)、6つのAVCapturePhoto
オブジェクトを提供します。複数の結果を追跡するには、各写真のを解決済みの設定のphotoCount
とexpectedPhotoCount
比較します。
注意
ライブ写真のキャプチャを要求すると、追加のデリゲートメソッドがそのプロセスに関するフィードバックを提供します。ライブ写真のキャプチャと保存を参照してください。
キャプチャが完了したらクリーンアップする
キャプチャに関するシステムのすべての作業が完了すると、写真出力はデリゲートのphotoOutput(_:didFinishCaptureFor:error:)
メソッドを呼び出します。この瞬間を使用して、キャプチャプロセスのアプリの一部を終了できます。
- キャプチャが複数の結果を予期している場合は、それらを
photoOutput(_:didFinishProcessingPhoto:error:)
(およびphotoOutput(_:didFinishProcessingLivePhotoToMovieFileAt:duration:photoDisplayTime:resolvedSettings:error:)
)メソッドにキャッシュしてから、結果をローカルストレージに保存するか、didFinishCaptureメソッドのフォトライブラリに追加します。 - キャプチャプロセスが他のリソースを管理している場合は、didFinishCaptureメソッドでそれらのリソースをクリーンアップします。キャプチャごとに個別の写真キャプチャデリゲートオブジェクトを使用する場合は、そのようなオブジェクトへの強い参照を削除するのによいタイミングです。
以下のコードは、複数の写真キャプチャデリゲートオブジェクトを管理する1つの方法を示しています。
class PhotoCaptureProcessor: NSObject, AVCapturePhotoCaptureDelegate { var completionHandler: () -> () = {} func photoOutput(_ output: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { completionHandler() } // ... other delegate methods to handle capture results... } // Keep a set of in-progress capture delegates. var capturesInProgress = Set<PhotoCaptureProcessor>() func shootPhoto() { // Make a new capture delegate for each capture and add it to the set. let captureProcessor = PhotoCaptureProcessor() capturesInProgress.insert(captureProcessor) // Schedule for the capture delegate to be removed from the set after capture. captureProcessor.completionHandler = { [weak self] in self?.capturesInProgress.remove(captureProcessor); return } self.photoOutput.capturePhoto(with: self.settingsForNextPhoto(), delegate: captureProcessor) }