如何在Swift中打开和关闭手电筒?

66

我想在我的Swift应用程序中添加手电筒功能。 我该如何操作?

15个回答

123

更新 #1: (torchActive 没有返回预期的值; 可能是因为它已被修改)

更新 #2: 适用于Swift 2.0

要切换闪光灯从开到关(不仅仅像疯狂猪的答案中所说的“开”),您可以使用以下方法:

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)
        }
    }
}

我使用嵌套的 do-catch 块来实现 Awesomeness 在评论中的建议。这种方式,即使 try device.setTorchModeOnWithLevel(1.0) 失败,设备也能正确解锁以进行配置。

更新 #3: 适用于 Swift 4:

(我对代码进行了一些个人喜好上的编辑)

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)
    }
}

要将闪光灯从打开状态切换到关闭状态(不仅仅是像疯狂的猪所说的“打开”),您可以使用以下方法:


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()
    }
}

2
我认为setTourchModeOnWithLevel调用需要在自己的try块中,以便在出现问题时可以解锁设备进行配置。 do { try device.setTorchModeOnWithLevel(1.0) } catch { device.unlockForConfiguration() } - Awesomeness
1
@Awesomeness 我采用了你的建议,但使用了嵌套的 do-catch 块,因为这样可以少写一行代码... 在 setTorchModeOnWithLevel(1.0) 的 catch 块内外都不需要调用 device.unlockForConfiguration()。 - Lyndsey Scott
当您快速按下手电筒按钮时,这个解决方案不是最快的,并且它会有轻微的延迟。 - Leon Jakonda
我建议使用AVCaptureDevice.maxAvailableTorchLevel而不是1.0。 - henrique

35

更新的Swift 4答案:

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")
    }
}

要实际打开或关闭它,请调用该函数并传递一个true或false的布尔值。

toggleTorch(on: true)toggleTorch(on: false)

我从Hacking with Swift获得了这个答案,但他们的示例中有一个错误。

他们使用了AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo),但这会导致一个错误,说defaultDevice不存在。所以我把它改成了AVCaptureDevice.default(for: AVMediaType.video)


1
我喜欢这段代码的编写方式。在我的应用程序中完美地运行。只需记得导入AVFoundation以使用手电筒。 - Josh

26

我已经更新了@Lyndsey Scott的优秀答案,以适应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)
        }
    }

4
对于新手(像我一样),我想补充说明,在Swift文件的视图控制器顶部,需要包含“import AVFoundation”。请注意保留原文意思,使翻译更通俗易懂。 - dmcknight
1
顺便提一下,我也在几个月前更新了我的Swift 2.0答案(这个答案是基于那个的),与这个答案不同的是,我的答案还处理了try device.setTorchModeOnWithLevel(1.0)失败的情况。 - Lyndsey Scott

11

Swift 5

许多人已经写了这个解决方案,但我想提出我在项目中想到的更简洁的方法:

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")
    }
}

正如评论中所提到的,当手电筒正在使用时,您也可以更改它的亮度级别,我发现这非常方便。

还需导入AVFoundation来使用手电筒功能。


7

对于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")
        }
    }
}

6

就像这样:

 func turnTorchOn(){

    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if device.hasTorch {
        device.lockForConfiguration(nil)
        device.setTorchModeOnWithLevel(1.0, error: nil)
        device.unlockForConfiguration()
    }


}

6

对于Xcode 9.1,Swift 4(更新后不会崩溃,即使没有手电筒):

   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)
            }
        }
    }
}

4
如果你想使用一个按钮来打开或关闭手电筒,这是代码:
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")
        }
    }

您可以在按钮点击函数中调用toggleTorch(),以打开和关闭手电筒。

3

解决方案适用于Swift 4,条件是是否有torch

 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")
            }
        }

解决方案是@Joshua Dance@Lance的结合。

3
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)")
        }
    }
}

示例(iOS 14.0):
//ContentView.swift

import SwiftUI

struct ContentView: View {
    @StateObject var torchState = TorchState()
    
    var body: some View {
          Toggle(isOn: $torchState.isOn) {
                Text("Torch")
          }
    }
}
        

很好,干净利落。正是我所需要的。谢谢! - user3687284

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接