17

I would like to know if it's possible to receive notification about autofocus inside an iPhone application?

I.E, does it exist a way to be notified when autofocus starts, ends, if it has succeed or failed... ?

If so, what is this notification name ?

Sly
  • 2,105
  • 5
  • 22
  • 28

4 Answers4

44

I find the solution for my case to find when autofocus starts / ends. It's simply dealing with KVO (Key-Value Observing).

In my UIViewController:

// callback
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if( [keyPath isEqualToString:@"adjustingFocus"] ){
        BOOL adjustingFocus = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1] ];
        NSLog(@"Is adjusting focus? %@", adjustingFocus ? @"YES" : @"NO" );
        NSLog(@"Change dictionary: %@", change);
    }
}

// register observer
- (void)viewWillAppear:(BOOL)animated{
    AVCaptureDevice *camDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    int flags = NSKeyValueObservingOptionNew; 
    [camDevice addObserver:self forKeyPath:@"adjustingFocus" options:flags context:nil];

    (...)   
}

// unregister observer
- (void)viewWillDisappear:(BOOL)animated{
    AVCaptureDevice *camDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [camDevice removeObserver:self forKeyPath:@"adjustingFocus"];

    (...)
}

Documentation:

Sly
  • 2,105
  • 5
  • 22
  • 28
  • This doesn't tell you whether autofocus failed, though. Even if adjustingFocus becomes false, it does not necessarily mean that the camera is in focus. – Kostub Deshmukh Aug 05 '15 at 18:56
  • 1
    This method also fails on iPhone 6/6Plus/6S/6S Plus class devices, as there is a different autofocus mode where adjustingFocus is not accurate. – Sean Langley May 02 '16 at 18:59
  • What's the value for ISO's key? – nr5 Jun 22 '17 at 15:17
  • 1
    Thanks Sean Langley for this helpful information. Apple documentation :"Note: On older devices that use contrast-detection auto-focus, the value of the AVCaptureDevice adjustingFocus changes during automatic focusing. On devices with focus pixels, focus changes are smaller and more frequent, so this property’s value does not change during focusing. Instead, observe the lensPosition property to see lens movements. " – Laurent Maquet Nov 10 '17 at 10:34
6

Swift 3

Set focus mode on your AVCaptureDevice instance:

do {
     try videoCaptureDevice.lockForConfiguration()
     videoCaptureDevice.focusMode = .continuousAutoFocus
     videoCaptureDevice.unlockForConfiguration()
} catch {}

Add observer:

videoCaptureDevice.addObserver(self, forKeyPath: "adjustingFocus", options: [.new], context: nil)

Override observeValue:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    guard let key = keyPath, let changes = change else { 
        return
    }

    if key == "adjustingFocus" {

        let newValue = changes[.newKey]
        print("adjustingFocus \(newValue)")
    }
}
sash
  • 8,423
  • 5
  • 63
  • 74
3

You can use modern Swift key value observing api to get callbacks when focusing starts and ends by observing AVCaptureDeviceInput.device.isAdjustingFocus property. In the example below, instance of AVCaptureDeviceInput is called captureDeviceInput.

Example:

self.focusObservation = observe(\.captureDeviceInput.device.isAdjustingFocus, options: .new) { _, change in
    guard let isAdjustingFocus = change.newValue else { return }

    print("isAdjustingFocus = \(isAdjustingFocus)")

}
jlajlar
  • 1,118
  • 11
  • 9
0

In Swift you can do it like this:

self.observation = videoDeviceInput.device.observe(\.isAdjustingFocus, options: [.old, .new]) { (object, change) in
     print("isAdjustingFocus, old = \(change.oldValue), new = \(change.newValue)")
}
noripcord
  • 3,412
  • 5
  • 29
  • 26