SwiftUI中.sheet弹出UIImagePicker点击搜索栏自动消失问题求助
解决思路
这个问题是SwiftUI与旧版UIKit组件UIImagePickerController集成时的常见兼容性bug,触发原因是@Environment(\.presentationMode)会误识别UIImagePickerController内部搜索栏唤起时的控制器跳转逻辑为主动关闭请求,导致整个sheet被意外销毁。可参考以下方案解决:
- 替换控制弹窗的状态变量,放弃使用系统自带的
presentationMode,改为传入自定义的Bool类型Binding变量控制sheet显隐,修改后的完整代码如下:
struct ImagePicker: UIViewControllerRepresentable { // 替换为自定义的显隐控制绑定 @Binding var isPresented: Bool @Binding var image: UIImage? var mode:UIView.ContentMode? func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController { let picker = UIImagePickerController() picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {} class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { var parent: ImagePicker init(_ parent: ImagePicker) { self.parent = parent } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { if let uiImage = info[.originalImage] as? UIImage { parent.image = uiImage } // 用自定义变量控制关闭 parent.isPresented = false } // 补充取消选择的回调 func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { parent.isPresented = false } } func makeCoordinator() -> Coordinator { Coordinator(self) } }
调用时将控制sheet显隐的绑定变量传入即可:
struct YourView: View { @State private var showImagePicker = false @State private var selectedImage: UIImage? var body: some View { Button("选择图片") { showImagePicker = true } .sheet(isPresented: $showImagePicker) { ImagePicker(isPresented: $showImagePicker, image: $selectedImage) } } }
替换为苹果官方推荐的新一代相册选择器
PHPickerViewController(兼容iOS 14及以上版本),该组件对SwiftUI的适配性更好,原生支持搜索、多选等能力,不会出现上述交互bug,性能也优于旧版的UIImagePickerController。若需要兼容iOS 14以下版本,可在sheet修饰符上额外添加
.interactiveDismissDisabled(true)配置,进一步屏蔽误触发的dismiss信号,配合自定义显隐绑定使用稳定性更高。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

