I'd like to add flashlight functionality to my app in Swift. How can I go about doing that?
15 Answers
Update #1: (torchActive
isn't returning the expected value; perhaps because it's been modified)
Update #2: For Swift 2.0
To toggle the flash from on to off (not just "on" as in mad pig's answer), you can use the following method:
func toggleFlash() {
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if (device.hasTorch) {
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureTorchMode.On) {
device.torchMode = AVCaptureTorchMode.Off
} else {
do {
try device.setTorchModeOnWithLevel(1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
}
I used nested do-catch blocks to implement Awesomeness's suggestion from the comments. This way, even if try device.setTorchModeOnWithLevel(1.0)
fails, the device is properly unlocked for configuration.
Update #3: For Swift 4:
(I edited the code a bit to my personal taste)
func toggleFlash() {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
guard device.hasTorch else { return }
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureDevice.TorchMode.on) {
device.torchMode = AVCaptureDevice.TorchMode.off
} else {
do {
try device.setTorchModeOn(level: 1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
Original answer:
To toggle the flash from on to off (not just "on" as in mad pig's answer), you can use the following method:
func toggleFlash() {
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if (device.hasTorch) {
device.lockForConfiguration(nil)
let torchOn = !device.torchActive
device.setTorchModeOnWithLevel(1.0, error: nil)
device.torchMode = torchOn ? AVCaptureTorchMode.On : AVCaptureTorchMode.Off
device.unlockForConfiguration()
}
}

- 401
- 5
- 13

- 37,080
- 10
- 92
- 128
-
2I think the `setTourchModeOnWithLevel` call needs to be in its own try block, so that it can unlock the device for configuration in the event that something goes wrong. ` do { try device.setTorchModeOnWithLevel(1.0) } catch { device.unlockForConfiguration() } ` – Awesomeness Dec 02 '15 at 14:52
-
1@Awesomeness I implemented your suggestion, but used a nested do-catch block instead since it's one less line of code... No need to call device.unlockForConfiguration() both within and outside of the setTorchModeOnWithLevel(1.0) catch block. – Lyndsey Scott Dec 02 '15 at 16:26
-
when you quickly press the flashlight button, this solution is not the fastest, and it works with a slight delay – Leon Jakonda Apr 13 '21 at 10:03
-
I suggest using AVCaptureDevice.maxAvailableTorchLevel instead of 1.0. – henrique Sep 08 '21 at 19:29
Updated Swift 4 Answer:
func toggleTorch(on: Bool) {
guard
let device = AVCaptureDevice.default(for: AVMediaType.video),
device.hasTorch
else { return }
do {
try device.lockForConfiguration()
device.torchMode = on ? .on : .off
device.unlockForConfiguration()
} catch {
print("Torch could not be used")
}
}
Then to actually turn it on or off, call the function and pass in a true or false boolean.
toggleTorch(on: true)
of toggleTorch(on: false)
I got this answer from Hacking with Swift, however their example had an error in it.
They used AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
but this produces an error saying defaultDevice
doesn't exist. So I changed it to AVCaptureDevice.default(for: AVMediaType.video)

- 317
- 1
- 11

- 8,847
- 4
- 67
- 72
-
1I like how this code was written. Worked perfectly in my app. Just remember to import AVFoundation to use the torch. – Josh Dec 29 '18 at 18:22
I've updated @Lyndsey Scott's great answer for Swift 2.0
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if (device.hasTorch) {
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureTorchMode.On) {
device.torchMode = AVCaptureTorchMode.Off
} else {
try device.setTorchModeOnWithLevel(1.0)
}
device.unlockForConfiguration()
} catch {
print(error)
}
}

- 2,181
- 2
- 27
- 52
-
4For the newbies (like me), I'd like to add that you need to include 'import AVFoundation' in the top of the view controller swift file. – dmcknight Jan 02 '16 at 16:45
-
1FYI I updated my answer for Swift 2.0 as well (the answer this one was based on) a few months ago and unlike this answer, my answer also handles the case where try device.setTorchModeOnWithLevel(1.0) fails. – Lyndsey Scott Mar 07 '16 at 17:31
Swift 5
The solution was already written by many, but I want to propose also the more concise one I came up in my project:
func toggleTorch(on: Bool) {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
guard device.hasTorch else { print("Torch isn't available"); return }
do {
try device.lockForConfiguration()
device.torchMode = on ? .on : .off
// Optional thing you may want when the torch it's on, is to manipulate the level of the torch
if on { try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel.significand) }
device.unlockForConfiguration()
} catch {
print("Torch can't be used")
}
}
As mentioned in the comment, you can also change the torch level when it's on, which I find quite handy.
Also import AVFoundation to use torch.

- 6,950
- 5
- 50
- 69

- 1,528
- 17
- 25
For swift 3
func toggleFlash() {
if let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo), device.hasTorch {
do {
try device.lockForConfiguration()
let torchOn = !device.isTorchActive
try device.setTorchModeOnWithLevel(1.0)
device.torchMode = torchOn ? .on : .off
device.unlockForConfiguration()
} catch {
print("error")
}
}
}

- 2,391
- 1
- 30
- 29
Like so:
func turnTorchOn(){
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if device.hasTorch {
device.lockForConfiguration(nil)
device.setTorchModeOnWithLevel(1.0, error: nil)
device.unlockForConfiguration()
}
}

- 788
- 6
- 10
For xcode 9.1, swift 4 (updated to not crash if no torch):
func toggleFlash() {
let device = AVCaptureDevice.default(for: AVMediaType.video)
if (device != nil) {
if (device!.hasTorch) {
do {
try device!.lockForConfiguration()
if (device!.torchMode == AVCaptureDevice.TorchMode.on) {
device!.torchMode = AVCaptureDevice.TorchMode.off
} else {
do {
try device!.setTorchModeOn(level: 1.0)
} catch {
print(error)
}
}
device!.unlockForConfiguration()
} catch {
print(error)
}
}
}
}

- 61
- 1
- 2
If you want to use only one button to on or off flashlight this is code;
func toggleTorch() {
guard
let device = AVCaptureDevice.default(for: AVMediaType.video),
device.hasTorch
else { return }
do {
try device.lockForConfiguration()
if device.torchMode == AVCaptureDevice.TorchMode.on
{
device.torchMode = .off
} else {
device.torchMode = .on
}
device.unlockForConfiguration()
} catch {
print("Torch could not be used")
}
}
you can call toggleTorch() in button click function to on and off flashlight.

- 579
- 4
- 17
Solution For Swift 4 With Condition torch is available or not
func flashlight() {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else{
return
}
if (device.hasTorch) {
do {
try device.lockForConfiguration()
if (device.torchMode == .on) {
device.torchMode = .off
} else {
device.torchMode = .on
}
device.unlockForConfiguration()
} catch {
print("Torch could not be used")
print(error)
}
}
else{
print("Torch is not available")
}
}
The Solution is Combination of @Joshua Dance And @Lance

- 1,993
- 2
- 25
- 40
SwiftUI
// TorchState.swift
import SwiftUI
import AVFoundation
class TorchState: ObservableObject {
@Published var isOn: Bool = false {
didSet {
toggleTorch(isOn)
}
}
private func toggleTorch(_ isOn: Bool) {
guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
do {
try device.lockForConfiguration()
device.torchMode = isOn ? .on : .off
if isOn {
try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel)
}
device.unlockForConfiguration()
} catch {
print("Error: \(error)")
}
}
}
Example (iOS 14.0):
//ContentView.swift
import SwiftUI
struct ContentView: View {
@StateObject var torchState = TorchState()
var body: some View {
Toggle(isOn: $torchState.isOn) {
Text("Torch")
}
}
}

- 7,979
- 1
- 64
- 49
Swift 4.2
if let device = AVCaptureDevice.default(for: AVMediaType.video) {
if (device.hasTorch) {
do {
try device.lockForConfiguration()
let torchOn = !device.isTorchActive
try device.setTorchModeOn(level: 1.0)
device.torchMode = torchOn ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
device.unlockForConfiguration()
} catch {
print(error.localizedDescription)
}
}
}

- 11
- 2
Swift version 5.2.4
func toggleFlash(on: Bool ) {
guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
do {
try device.lockForConfiguration()
device.torchMode = on ? .on : .off
if on {
try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel)
}
device.unlockForConfiguration()
} catch {
print("Error: \(error)")
}
}

- 681
- 8
- 7
Refactored. Swift 5.4
import AVFoundation
extension UIDevice {
static func toggleFlashLight() {
guard let device = AVCaptureDevice.default(for: AVMediaType.video),
device.hasTorch else { return }
do {
try device.lockForConfiguration()
try device.setTorchModeOn(level: 1.0)
device.torchMode = device.isTorchActive ? .off : .on
device.unlockForConfiguration()
} catch {
assert(false, "error: device flash light, \(error)")
}
}
}

- 471
- 6
- 7
Decided to add a solution here using defer
:
struct TorchError: Error {
var description: String
}
func toggleTorch() throws {
guard let device = AVCaptureDevice.default(for: .video) else {
throw TorchError(description: "Failed to acquire default capture device")
}
if device.hasTorch {
try device.lockForConfiguration()
defer {
device.unlockForConfiguration()
}
let isTorchOn = device.torchMode == .on
device.torchMode = isTorchOn ? .off : .on
} else {
throw TorchError(description: "Capture device is missing torch functionality")
}
}

- 21
- 3
- 5
Swift 4.1
@objc func Flash() {
let device = AVCaptureDevice.default(for: AVMediaType.video)
if (device?.hasTorch)! {
do {
try device?.lockForConfiguration()
if (device?.torchMode == AVCaptureDevice.TorchMode.on) {
device?.torchMode = AVCaptureDevice.TorchMode.off
} else {
do {
try device?.setTorchModeOn(level: 1.0)
} catch {
print(error)
}
}
device?.unlockForConfiguration()
} catch {
print(error)
}
}
}