You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI+UIImagePickerController:相机开启时保持闪光灯常亮

实现UIImagePickerController闪光灯常亮

问题核心:直接在makeUIViewController中操作闪光灯会失效,因为此时相机会话尚未完全初始化,系统后续会重置闪光灯状态,导致短暂亮起后熄灭。以下是修改方案:

步骤1:自定义UIImagePickerController子类

创建子类并重写viewDidAppear方法,在相机界面完全加载后开启闪光灯常亮:

class CustomImagePickerController: UIImagePickerController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        do {
            try device.lockForConfiguration()
            try device.setTorchModeOn(level: 1.0)
            device.unlockForConfiguration()
        } catch {
            print("开启闪光灯失败: \(error)")
        }
    }
}

步骤2:修改ImagePicker结构体

将原有的UIImagePickerController替换为自定义子类,移除无效的toggleFlash调用:

struct ImagePicker: UIViewControllerRepresentable {
    
    @Binding var isShown: Bool
    @Binding var image: UIImage?
    @Binding var didTapCapture: Bool
    
    func updateUIViewController(_ uiViewController: CustomImagePickerController, context: Context) {
        uiViewController.showsCameraControls = false
        if didTapCapture {
            uiViewController.takePicture()
            didTapCapture = false
        }
    }
    
    func makeCoordinator() -> ImagePickerCoordinator {
        ImagePickerCoordinator(isShown: $isShown, image: $image)
    }
    
    func makeUIViewController(context: Context) -> CustomImagePickerController {
        let picker = CustomImagePickerController()
        picker.delegate = context.coordinator
        picker.sourceType = .camera
        picker.showsCameraControls = false
        picker.modalPresentationStyle = .fullScreen
        return picker
    }
}

步骤3:在Coordinator中处理闪光灯关闭

在相机关闭时(拍照完成或取消)关闭闪光灯,避免资源占用:

class ImagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    
    @Binding var isShown: Bool
    @Binding var image: UIImage?
    
    init(isShown: Binding<Bool>, image: Binding<UIImage?>) {
        _isShown = isShown
        _image = image
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        let uiImage = info[.originalImage] as! UIImage
        image = uiImage
        closeFlash()
        isShown = false
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        closeFlash()
        isShown = false
    }
    
    private func closeFlash() {
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        do {
            try device.lockForConfiguration()
            device.torchMode = .off
            device.unlockForConfiguration()
        } catch {
            print("关闭闪光灯失败: \(error)")
        }
    }
}

原理说明

  • viewDidAppear是相机界面完全加载、会话启动后的回调,此时设置闪光灯状态不会被系统重置。
  • 自定义子类确保闪光灯逻辑与相机生命周期绑定,避免时机错误。
  • 关闭相机时主动关闭闪光灯,符合资源管理规范。

内容的提问来源于stack exchange,提问作者Manan Vij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 14:15:38