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

Swift开发iOS相机App点击Use Photo按钮后CameraView冻结问题

iOS 相机应用拍照后CameraView冻结问题排查

问题现象

已授权相册访问权限的前提下,用户完成拍照点击「Use Photo」按钮时,拍摄的照片可正常保存至系统相册,但CameraView会完全冻结无响应。

相关代码片段

ContentView 代码

struct ContentView: View {
    var body: some View {
        CameraView()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CameraView 中 Coordinator 部分代码

extension CameraView {
    class Coordinator : NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        var parent: CameraView
        
        init(_ parent: CameraView) {
            self.parent = parent
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            fatalError("Cancel button pressed!")
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                CustomizeView()
            }
        }
    }
}

「Use Photo」按钮对应控制逻辑

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) // 执行到此处后CameraView冻结
}

问题根因

  1. 核心冻结原因:实现UIImagePickerControllerDelegate的选择完成回调后,没有手动调用dismiss关闭当前弹出的UIImagePicker控制器。系统不会自动移除该控制器,保存照片完成后picker仍覆盖在界面顶层拦截所有交互,表现为CameraView完全无响应。
  2. 附加逻辑错误:
    • 取消回调中直接调用fatalError,会导致用户点击取消按钮时应用直接崩溃。
    • 代理回调中直接初始化CustomizeView()属于错误写法,SwiftUI的View是值类型,直接初始化不会触发正确的页面跳转逻辑,反而会导致UI状态混乱。

修复方案

  1. 在didFinishPickingMediaWithInfo回调中,先执行picker.dismiss(animated: true)关闭图片选择器,解除UI交互阻塞。
  2. 移除取消回调中的fatalError,替换为正常dismiss picker的逻辑,避免点取消崩溃。
  3. 给CameraView添加绑定的状态变量,通过状态控制CustomizeView的弹出,不要在代理回调中直接初始化SwiftUI视图。

修复后代码参考

CameraView 状态定义

struct CameraView: View {
    @State private var capturedImage: UIImage?
    @State private var isShowCustomizePage = false

    var body: some View {
        // 原有相机页面逻辑
        .sheet(isPresented: $isShowCustomizePage) {
            if let img = capturedImage {
                CustomizeView(editImage: img)
            }
        }
    }
}

修复后的 Coordinator 代理实现

extension CameraView {
    class Coordinator : NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        var parent: CameraView
        
        init(_ parent: CameraView) {
            self.parent = parent
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            picker.dismiss(animated: true)
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            // 先关闭picker,解决冻结问题
            picker.dismiss(animated: true)
            guard let image = info[.originalImage] as? UIImage else { return }
            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
            // 赋值后通过状态触发页面跳转
            parent.capturedImage = image
            parent.isShowCustomizePage = true
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:51:25