SwiftUI UIIMagePickerController查找/搜索字段奇怪行为



我正在使用UIImagePickerController从用户的照片库中选择图像。除了用户用放大镜图标点击字段以搜索库时,所有操作都很好。有时它会解雇ImagePicker,有时它什么也不做,偶尔它会像预期的那样工作。。。有什么想法吗?

显示工作表的代码:

Button(action: {}) {
ZStack {
Image(systemName: "photo")
.foregroundColor(darkMode ? .white : .black)
}
}
.frame(width: 44, height: 44)
.onTapGesture {
showPhotoLibrary.toggle()
}
.sheet(isPresented: $showPhotoLibrary) {
ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
}

ImagePicker:

import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {

var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var selectedImage: UIImage
@Environment(.presentationMode) private var presentationMode

func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {

let imagePicker = UIImagePickerController()
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
return imagePicker
}

func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {

}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}

internal func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
parent.selectedImage = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}

func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}

我见过很多人为此而挣扎,苹果开发论坛上到处都是,所以我想我会尝试解决它。从我自己的测试来看,我认为问题的原因是UIImagePickerController被设计为使用父视图控制器的present方法来呈现,而不是用作SwiftUI呈现的工作表的根视图控制器,就像苹果(在他们的示例代码中(和其他人似乎正在做的那样。下面是我不完整的测试代码,它显示了一个正在工作的图像选择器,它可以在哪里进行搜索,也可以向下拖动以忽略它,所以我认为这可能是正确的解决方案。

其思想是,我们使用UIViewControllerRepresentable来呈现我们自己的自定义视图控制器,当当前布尔值发生变化时,该控制器会显示或取消图像选择器视图控制器。

struct ImagePickerTest: View {
@State var show = false
@State var image1: UIImage?

var body: some View {
VStack {
Button("Hello, World!") {
show.toggle()
}
Text("image: (image1?.description ?? "" )")
}
.imagePicking(isPresented: $show, selectedImage: $image1)
}
}

extension View {
// this could be refactored into a `ViewModifier`
func imagePicking(isPresented: Binding<Bool>, selectedImage: Binding<UIImage?>) -> some View {
ZStack {
ImagePicking(isPresented: isPresented, selectedImage: selectedImage)
self
}
}
}
class MyViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{

var dismissPicker: (() -> Void)?
var selectImage: ((UIImage) -> Void)?

func showPickerIfNecessary() {
if self.presentedViewController != nil {
return
}
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true)
}

func hidePickerIfNecessary() {
if let vc = self.presentedViewController {
vc.dismiss(animated: true)
}
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("imagePickerControllerDidCancel")
dismissPicker?()
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
print("didFinishPickingMediaWithInfo")
if let image = (info[.editedImage] ?? info[.originalImage]) as? UIImage {
selectImage?(image)
dismissPicker?()
}
}
}
struct ImagePicking: UIViewControllerRepresentable {

@Binding var isPresented: Bool
@Binding var selectedImage: UIImage?

func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
uiViewController.dismissPicker = {
isPresented = false
}
uiViewController.selectImage = { image in
selectedImage = image
}

if isPresented {
uiViewController.showPickerIfNecessary()
} else {
uiViewController.hidePickerIfNecessary()
}
}

func makeUIViewController(context: Context) -> some MyViewController {
MyViewController()
}
}

在我开始之前,我验证了OP的代码在键入搜索时失败,它崩溃了,出现了以下错误:

2022-08-31 22:39:17.808899+0100 Test[66967:5425868] [UI] -[PUPhotoPickerHostViewController viewServiceDidTerminateWithError:] Error Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}