PHPickerViewController选中照片预览无关闭按钮问题求助
问题解决
问题1:点击“显示已选(x)”无法关闭预览界面
这个问题源于已选资源列表变化时,PHPickerViewController的预选资源未同步更新,导致预览界面状态与实际选中状态不一致,无法触发关闭逻辑。需在updateUIViewController方法中同步更新picker的预选资源:
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { var assetIdentifiers = [String]() for asset in messageFormViewModel.photoPickerMedia { assetIdentifiers.append(asset.id) } // 更新picker的预选资源ID uiViewController.configuration.preselectedAssetIdentifiers = assetIdentifiers }
同时修正picker(_:didFinishPicking:)中的逻辑:PHPicker返回的results是用户最终选择的完整列表,需先清空已选列表再添加新内容,避免重复或顺序混乱:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) // 清空原有已选内容,再添加新选择的资源 parent.messageFormViewModel.photoPickerMedia.removeAll() for result in results { guard let id = result.assetIdentifier else { continue } let provider = result.itemProvider if provider.canLoadObject(ofClass: UIImage.self) { provider.loadObject(ofClass: UIImage.self) { image, _ in guard let image = image as? UIImage else { return } let viewModel = PhotoPickerViewModel( id: id, jpgData: image.jpegData(compressionQuality: 1.0)!, image: image, size: image.size ) DispatchQueue.main.async { self.parent.messageFormViewModel.photoPickerMedia.append(viewModel) } } } } }
问题2:导航栏右侧存在不可见按钮
这是SwiftUI与UIKit导航栏交互的布局兼容性问题,可通过以下方式解决:
- 在
makeUIViewController方法中设置picker的modal展示样式:
let picker = PHPickerViewController(configuration: config) picker.delegate = context.coordinator // 设置全屏展示,避免导航栏布局冲突 picker.modalPresentationStyle = .fullScreen
- 在SwiftUI中使用
fullScreenCover而非sheet来present picker:
// 示例:在你的SwiftUI视图中触发picker .fullScreenCover(isPresented: $showPicker) { PhotoPickerView(messageFormViewModel: yourViewModel) }
完整修正代码
struct PhotoPickerView: UIViewControllerRepresentable { //MARK: - Properties @ObservedObject var messageFormViewModel: MessageFormViewModel // 外部传入的ViewModel需用@ObservedObject //MARK: - View func makeUIViewController(context: Context) -> PHPickerViewController { var assetIdentifiers = [String]() let photoLibrary = PHPhotoLibrary.shared() var config = PHPickerConfiguration(photoLibrary: photoLibrary) config.filter = .images config.selectionLimit = getAttachmentLimit() config.selection = .ordered for asset in messageFormViewModel.photoPickerMedia { assetIdentifiers.append(asset.id) } config.preselectedAssetIdentifiers = assetIdentifiers let picker = PHPickerViewController(configuration: config) picker.delegate = context.coordinator picker.modalPresentationStyle = .fullScreen return picker } func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { var assetIdentifiers = [String]() for asset in messageFormViewModel.photoPickerMedia { assetIdentifiers.append(asset.id) } uiViewController.configuration.preselectedAssetIdentifiers = assetIdentifiers } private func getAttachmentLimit() -> Int { guard let attachmentLimit = ApplicationSettingsManager.shared.settings?.limits.maxFileAttachments else { return 0 } return attachmentLimit } //MARK: - Coordinator func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, PHPickerViewControllerDelegate { let parent: PhotoPickerView init(_ parent: PhotoPickerView) { self.parent = parent } func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) parent.messageFormViewModel.photoPickerMedia.removeAll() for result in results { guard let id = result.assetIdentifier else { continue } let provider = result.itemProvider if provider.canLoadObject(ofClass: UIImage.self) { provider.loadObject(ofClass: UIImage.self) { image, _ in guard let image = image as? UIImage else { return } let viewModel = PhotoPickerViewModel( id: id, jpgData: image.jpegData(compressionQuality: 1.0)!, image: image, size: image.size ) DispatchQueue.main.async { self.parent.messageFormViewModel.photoPickerMedia.append(viewModel) } } } } } } }
额外注意
- 外部传入的ViewModel需使用
@ObservedObject而非@StateObject,@StateObject仅适用于当前视图内部创建的ViewModel。
内容的提问来源于stack exchange,提问作者BrettS
相关产品推荐
相关产品推荐

