これは最初は非常に複雑に思えます...しかし、非常にシンプルになりました.Appleはすでに私たちのために99%の仕事をしてくれました. 「 subjectAreaChangeMonitoringEnabled 」をオンに設定し、「AVCaptureDeviceSubjectAreaDidChangeNotification」に KVO を登録するだけです。iOS 6.1 のドキュメント:
このプロパティの値は、照明の変化、大幅な動きなど、ビデオのサブジェクト領域の変化を受信機が監視する必要があるかどうかを示します。サブジェクト エリアの変更監視が有効になっている場合、キャプチャ デバイス オブジェクトは、サブジェクト エリアの変更を検出するたびに AVCaptureDeviceSubjectAreaDidChangeNotification を送信します。この時点で、関心のあるクライアントは、再フォーカス、露出、ホワイト バランスの調整などを希望する場合があります。
このプロパティの値を変更する前に、lockForConfiguration: を呼び出して、デバイスの構成プロパティへの排他的アクセスを取得する必要があります。そうしないと、このプロパティの値を設定すると例外が発生します。デバイスの構成が完了したら、unlockForConfiguration を呼び出してロックを解除し、他のデバイスが設定を構成できるようにします。
キー値観察を使用して、このプロパティの値の変化を観察できます。
(さらに良いことに、多くのコーナー ケースを処理する必要はありません。デバイスが POI で「フォーカスの調整」の最中にあり、コンテンツが変更された場合はどうなるでしょうか?デバイスが中央でオート フォーカスにフォールバックするのは望ましくありません。 、フォーカスアクションを終了させたい.「エリア変更通知」は、フォーカスが完了した後にのみトリガーされます.)
私のプロジェクトのサンプル コード スニペット。(構造は、公式の AVFoundation サンプル AVCam に従っているため、簡単に配置して試すことができます):
// CameraCaptureManager.m
@property (nonatomic, strong) AVCaptureDevice *backFacingCamera;
- (id) init{
self = [super init];
if (self){
// TODO: more of your setup code for AVFoundation capture session
for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if (device.position == AVCaptureDevicePositionBack){
self.backFacingCamera = device;
}
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
void (^subjectAreaDidChangeBlock)(NSNotification *) = ^(NSNotification *notification) {
if (self.videoInput.device.focusMode == AVCaptureFocusModeLocked ){
// All you need to do is set the continuous focus at the center. This is the same behavior as
// in the stock Camera app
[self continuousFocusAtPoint:CGPointMake(.5f, .5f)];
}
};
self.subjectAreaDidChangeObserver = [notificationCenter addObserverForName:AVCaptureDeviceSubjectAreaDidChangeNotification
object:nil
queue:nil
usingBlock:subjectAreaDidChangeBlock];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[self addObserver:self forKeyPath:keyPathAdjustingFocus options:NSKeyValueObservingOptionNew context:NULL];
}
return self;
}
-(void) dealloc{
// Remove the observer when done
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self.deviceOrientationDidChangeObserver];
}
- (BOOL) setupSession{
BOOL sucess = NO;
if ([self.backFacingCamera lockForConfiguration:nil]){
// Turn on subject area change monitoring
self.backFacingCamera.subjectAreaChangeMonitoringEnabled = YES;
}
[self.backFacingCamera unlockForConfiguration];
// TODO: Setup add input etc...
return sucess;
}