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

SwiftUI中使用UIImagePicker选相册图片无法捕获用户操作如何解决

解决方案

你的代码核心问题是没有遵循UIViewControllerRepresentable的标准实现规范,直接将ChooseImageView实例本身设置为UIImagePickerController的代理,SwiftUI不会持有该实例作为代理的引用,因此代理方法无法被触发。你需要使用SwiftUI要求的Coordinator作为代理对象,同时调整选择器的调用方式。

修改后的完整实现

1. 重写ChooseImageView

struct ChooseImageView: UIViewControllerRepresentable {
    // 回传选中的图片到父视图
    @Binding var selectedImage: UIImage?
    // 控制选择器的展示/关闭状态
    @Binding var isPresented: Bool

    // 生成Coordinator作为代理载体
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let libraryPicker = UIImagePickerController()
        libraryPicker.sourceType = .photoLibrary
        // 把Coordinator设为代理,而非self
        libraryPicker.delegate = context.coordinator
        return libraryPicker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}

    // 代理方法全部放到Coordinator中实现
    class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        let parent: ChooseImageView

        init(parent: ChooseImageView) {
            self.parent = parent
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            // 这里的print会正常输出
            print("I got a change")
            // 取出选中的原图
            if let image = info[.originalImage] as? UIImage {
                parent.selectedImage = image
            }
            // 关闭选择器
            parent.isPresented = false
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.isPresented = false
        }
    }
}

2. 调整父视图PhotoPage的实现

相册选择器通常以弹窗形式弹出,不要直接嵌入到普通视图层级中:

struct PhotoPage: View {
    // 存储用户选中的图片
    @State private var selectedImage: UIImage?
    // 控制选择器是否弹出
    @State private var showImagePicker = false

    var body: some View {
        VStack(alignment: .center, spacing: 20) {
            // 选中后展示图片
            if let image = selectedImage {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .frame(height: 200)
            }
            // 点击按钮唤起相册选择器
            Button("从相册选择照片") {
                showImagePicker = true
            }
        }
        .sheet(isPresented: $showImagePicker) {
            ChooseImageView(selectedImage: $selectedImage, isPresented: $showImagePicker)
        }
    }
}

注意事项

  • 你需要在项目的Info.plist中添加相册访问权限说明,添加key为Privacy - Photo Library Usage Description,value填写权限用途描述,比如"需要访问相册以选择照片",否则App会在访问相册时直接崩溃。
  • 若你的App最低支持iOS 14及以上版本,可以直接使用SwiftUI原生的PhotosPicker组件,不需要自行桥接UIKit,实现逻辑更简单。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 01:00:01