从相册选取图片时触发线程错误,求解决方法
问题解决:从相册选图时的后台线程更新错误
问题原因
PHPicker的itemProvider.loadObject方法会在后台线程执行闭包回调,而SwiftUI要求所有状态(包括@Binding绑定的变量)的更新必须在主线程完成,直接在闭包里赋值就会触发这个错误。
修复方案
把更新@Binding变量的代码放到主线程队列里执行,用DispatchQueue.main.async包裹赋值操作即可。
修改后的完整代码:
struct ImagePicker: UIViewControllerRepresentable { @Binding var image: UIImage? class Coordinator: NSObject, PHPickerViewControllerDelegate { var parent: ImagePicker init(_ parent: ImagePicker) { self.parent = parent } func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let provider = results.first?.itemProvider else { return } if provider.canLoadObject(ofClass: UIImage.self) { provider.loadObject(ofClass: UIImage.self) { image, _ in // 切换到主线程更新绑定变量 DispatchQueue.main.async { self.parent.image = image as? UIImage } } } } } func makeUIViewController(context: Context) -> PHPickerViewController { var config = PHPickerConfiguration() config.filter = .images let picker = PHPickerViewController(configuration: config) picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(self) } }
补充说明
所有涉及SwiftUI视图状态变更的操作(比如修改@State、@Binding、@Published变量)都必须在主线程执行,这是SwiftUI的线程安全要求。如果遇到异步回调场景,一定要确认回调所在线程,非主线程的话就切换到主线程再更新状态。
内容的提问来源于stack exchange,提问作者dunoiww
相关产品推荐
相关产品推荐

