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

SwiftUI中UIImagePickerController自动拍照功能失效问题

解决SwiftUI中UIImagePickerController自动拍照的问题

你的问题核心是调用takePicture()的时机不对——在updateUIViewController阶段,UIImagePickerController的相机界面还未完全初始化完成,此时调用拍照方法不会生效,也无法触发代理回调。下面是修正方案:

修正思路

利用UIViewController的生命周期方法,在相机界面完全呈现后(即viewDidAppear关联的导航控制器回调阶段)调用takePicture(),同时通过标记位避免重复触发自动拍照。

修改后的完整代码

import Foundation
import SwiftUI
import UIKit
import MobileCoreServices

class ImagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    @Binding var isShown: Bool
    @Binding var image: UIImage?
    // 标记是否需要执行自动拍照
    var shouldAutoCapture: Bool = true
    
    init(isShown: Binding<Bool>, image: Binding<UIImage?>) {
        _isShown = isShown
        _image = image
    }
    
    // 监听picker的界面呈现完成事件
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        guard let picker = viewController as? UIImagePickerController, shouldAutoCapture else { return }
        
        // 相机界面已完全加载,执行自动拍照
        picker.takePicture()
        // 标记为已执行,避免重复拍照
        shouldAutoCapture = false
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        print("拍照成功,进入回调")
        if let uiImage = info[.originalImage] as? UIImage {
            image = uiImage
        }
        isShown = false
        picker.dismiss(animated: true)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        isShown = false
    }
}

struct ImagePicker: UIViewControllerRepresentable {
    @Binding var isShown: Bool
    @Binding var image: UIImage?
    
    func makeCoordinator() -> ImagePickerCoordinator {
        ImagePickerCoordinator(isShown: $isShown, image: $image)
    }
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        picker.sourceType = .camera
        picker.cameraCaptureMode = .photo
        picker.allowsEditing = false
        picker.showsCameraControls = false
        return picker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
        // 当isShown从false变为true时,重置自动拍照标记
        if isShown {
            context.coordinator.shouldAutoCapture = true
        }
    }
}

关键说明

  1. 生命周期监听:通过UINavigationControllerDelegate的navigationController(_:didShow:animated:)方法,确保相机界面完全加载后再执行拍照操作。
  2. 避免重复拍照:用shouldAutoCapture标记位控制只自动拍一次,每次isShown切换为true时重置该标记,支持多次触发相机自动拍照。
  3. 安全处理:将原代码中强制解包UIImage改为可选绑定,避免因数据异常导致崩溃。

额外注意事项

  • 必须在Info.plist中添加相机权限描述(NSCameraUsageDescription),否则相机无法正常启动。
  • 如果需要自定义拍照延迟或重复拍照逻辑,可在navigationController(_:didShow:animated:)中添加DispatchQueue延迟执行,或调整shouldAutoCapture的重置时机。

内容的提问来源于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 00:15:39