Search code examples
iosavfoundationnsnotifications

How to know when AVCaptureDevice torch light turns off?


I have a view controller based on AVCam, and I added a UIButton for toggling the torch light. Here's the code that performs that:

- (IBAction)toggleTorchLight:(id)sender {
// See: http://stackoverflow.com/questions/11726543/how-to-turn-flashlight-on-off-using-one-button
AVCaptureDevice *flashLight = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([flashLight isTorchAvailable] && [flashLight isTorchModeSupported:AVCaptureTorchModeOn]){
    if ([flashLight lockForConfiguration:nil]){
        if ([flashLight isTorchActive]) {
            [flashLight setTorchMode:AVCaptureTorchModeOff];
            [(UIButton *)sender setTintColor:[UIColor blackColor]];
        }
        else {
            [flashLight setTorchMode:AVCaptureTorchModeOn];
            [(UIButton *)sender setTintColor:[UIColor yellowColor]];
        }
        [flashLight unlockForConfiguration];
    }
}

You'll notice I turn the button yellow when the light is on. The problem is that the torch light also turns off when the app is sent to the background, when the view controller changes, when an alert view controller is presented, etc. These events turn the torch light off but I also need to make the button black again.

Instead of turning the button black for each of these individual scenarios, is there a simple way, like receiving a notification when the light turns off? I've tried AVCaptureDeviceWasDisconnectedNotification, overriding becomeFirstResponder and viewDidDisappear, none of them worked.

Any suggestions?


Solution

  • First define a context address:

    static void * TorchActiveContext = &TorchActiveContext;
    

    Then in the addObservers method:

    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [videoDevice addObserver:self forKeyPath:@"torchActive" options:NSKeyValueObservingOptionNew context:TorchActiveContext];
    

    In the removeObservers method:

    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [videoDevice removeObserver:self forKeyPath:@"torchActive" context:TorchActiveContext];
    

    In observeValueForKeyPath

    if (context == TorchActiveContext) {
        UIColor *color = ((AVCaptureDevice*)object).torchActive ? [UIColor yellowColor] : [UIColor blackColor];
        [self.torchLightButton setTintColor:color];
    }