Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you set a device's flash mode in Swift 4?

Tags:

ios

swift

camera

I'm calling a function to attempt to turn on my device's flash:

private func flashOn(device:AVCaptureDevice)
{
    print("flashOn called");
    do {

        try device.lockForConfiguration()
        // line below returns warning 'flashMode' was deprecated in iOS 10.0: Use AVCapturePhotoSettings.flashMode instead.
        device.flashMode = AVCaptureDevice.FlashMode.auto
        device.unlockForConfiguration()

    } catch {

        // handle error
        print("flash on error");
    }

}

Setting device.flashMode to AVCaptureDevice.FlashMode.auto brings up the warning "'flashMode' was deprecated in iOS 10.0: Use AVCapturePhotoSettings.flashMode instead.". Even though it is just a warning, it does not enable the flash when testing my app, so I change that line to:

device.flashMode = AVCaptureDevice.FlashMode.auto

So I set the line to this, like it suggests:

AVCapturePhotoSettings.flashMode = AVCaptureDevice.FlashMode.auto

And I get the error "Instance member 'flashMode' cannot be used on type 'AVCapturePhotoSettings'"

So I have no idea how to set the flash in Xcode version 9 using Swift 4.0. All the answers I've found in Stack Overflow have been for previous versions.

like image 950
Chewie The Chorkie Avatar asked Nov 13 '17 21:11

Chewie The Chorkie


2 Answers

I've been facing the same problem. Unfortunately, many useful methods got deprecated in iOS10 and 11. Here is how I managed to resolve it:

AVCapturePhotoSettings object is unique and cannot be reused, so you need to get new settings every time using this method:

/// the current flash mode
private var flashMode: AVCaptureDevice.FlashMode = .auto

/// Get settings
///
/// - Parameters:
///   - camera: the camera
///   - flashMode: the current flash mode
/// - Returns: AVCapturePhotoSettings
private func getSettings(camera: AVCaptureDevice, flashMode: AVCaptureDevice.FlashMode) -> AVCapturePhotoSettings {
    let settings = AVCapturePhotoSettings()

    if camera.hasFlash {
        settings.flashMode = flashMode
    }
    return settings
}

As you can see, lockConfiguration is not needed.

Then simply use it while capturing photo:

 @IBAction func captureButtonPressed(_ sender: UIButton) {
    let settings = getSettings(camera: camera, flashMode: flashMode)
    photoOutput.capturePhoto(with: settings, delegate: self)
}

Hope it will help.

like image 62
Crunkz Avatar answered Nov 17 '22 21:11

Crunkz


For objective C:

- (IBAction)turnTorchOn: (UIButton *) sender {
    sender.selected = !sender.selected;
    BOOL on;
    if (sender.selected) {
        on = true;
    } else {
        on = false;
    }
    // check if flashlight available
    Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
    if (captureDeviceClass != nil) {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCapturePhotoSettings *photosettings = [AVCapturePhotoSettings photoSettings];
        if ([device hasTorch] && [device hasFlash]) {
            [device lockForConfiguration:nil];
            if (on) {
                [device setTorchMode:AVCaptureTorchModeOn];
                photosettings.flashMode = AVCaptureFlashModeOn;
                //torchIsOn = YES; //define as a variable/property if you need to know status
            } else {
                [device setTorchMode:AVCaptureTorchModeOff];
                 photosettings.flashMode = AVCaptureFlashModeOn;
                //torchIsOn = NO;
            }
            [device unlockForConfiguration];
        }
    }
 }
like image 41
guru Avatar answered Nov 17 '22 21:11

guru