SwiftUI集成PHPickerViewController点击搜索栏报无法加载照片错误
根因
这是iOS 15系统的已知缺陷,和TCA架构无关,问题出在SwiftUI模态转场动画与系统照片选择器扩展进程的冲突:
- PHPicker、UIImagePicker在iOS15上运行在独立的系统扩展进程中,不属于App本身的进程
- 点击搜索栏触发键盘弹出时,SwiftUI默认的模态转场动画逻辑会和扩展进程的UI更新逻辑冲突,导致系统直接kill掉照片选择器的扩展进程,因此会出现
Connection to plugin invalidated报错和无法加载的提示 - 录屏时系统会全局禁用部分非核心动画,冲突逻辑不会触发,因此问题不会复现;UIKit的present动画逻辑和SwiftUI不同,不会触发该冲突,因此UIKit测试项目运行正常
可行解决方案
该问题在iOS 16及以上版本已经被苹果官方修复,仅需要对iOS 15版本做兼容处理即可,可任选以下方案:
- 方案1:弹出选择器时禁用模态动画(改动最小、兼容性最高)
在触发弹出sheet的逻辑中,iOS15版本禁用动画即可:Button("选择照片") { if #available(iOS 16, *) { showPicker = true } else { // iOS15下禁用动画弹出 withAnimation(nil) { showPicker = true } } } .sheet(isPresented: $showPicker) { ImagePicker(store: store) } - 方案2:修改UIViewControllerRepresentable实现,不直接返回PHPicker实例
外层套一个空白的UIViewController,通过空白VC来present PHPicker,规避SwiftUI直接管理选择器VC的布局动画问题,核心逻辑如下:public func makeUIViewController(context: Context) -> UIViewController { // 创建空白VC作为载体 let dummyVC = UIViewController() // 配置PHPicker var config = PHPickerConfiguration() config.filter = .images let picker = PHPickerViewController(configuration: config) picker.delegate = context.coordinator // 空白VC加载完成后自动弹出选择器 DispatchQueue.main.async { dummyVC.present(picker, animated: true) } return dummyVC } // 对应调整Coordinator的关闭逻辑:先dismiss PHPicker,再触发外层SwiftUI的sheet关闭 - 方案3:完全使用UIKit逻辑弹出选择器
直接获取当前根VC,用UIKit的present方法弹出PHPicker实例,完全绕开SwiftUI的sheet管理逻辑,和UIKit测试项目的实现逻辑完全一致。
内容的提问来源于stack exchange,提问作者Fogmeister
相关产品推荐
相关产品推荐

