AFTER tapping to take picture, I want to lock exposure and turn off torch as soon as exposure is no longer adjusting. So, I added an observer to handle adj
It is almost certainly a timing issue. Call captureStillImageAsynchronouslyFromConnection:completionHandler:
inside your if
block. Then the capture will always be executed after exposure has been locked.
if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) {
dispatch_async(dispatch_get_main_queue(),
^{
NSError *error = nil;
if ([self.inputDevice lockForConfiguration:&error]) {
//code to lock exposure here
//take photo here
}
});
}
I got something similar to happen by using flash instead of the torch. I have an observer for @"videoDevice.flashActive"
as well. I did try using exposureModeLocked
first, but it didn't work for me either.
The code below probably doesn't just work on its own, but it's simplified from what I did.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
{
if (context == AdjustingExposureContext)
{
self.isAdjustingExposure = [change[NSKeyValueChangeNewKey] boolValue];
}
else if (context == FlashModeChangedContext)
{
self.isFlashActive = [change[NSKeyValueChangeNewKey] boolValue];
if (!self.flashActive)
{
[self captureImage]; // QUICKLY! capture 2nd image without
} // flash before exposure adjusts
}
if (!self.isAdjustingExposure && self.flashActive)
{
[self removeObserver:self forKeyPath:@"videoDevice.adjustingExposure" context:AdjustingExposureContext];
[self captureImage]; // capture 1st image with the flash on
}
}
Now in the callback for captureStillImageAsynchronouslyFromConnection:
,
if (self.isFlashActive)
[self.videoDeviceInput.device setFlashMode:NO];
However, if you need to take more than one photo without flash at the lowered exposure, this strategy may not work.