首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHPickerViewController点击搜索得到错误.“无法加载照片”

PHPickerViewController点击搜索得到错误.“无法加载照片”
EN

Stack Overflow用户
提问于 2021-09-23 19:51:28
回答 4查看 1.6K关注 0票数 10

我正在尝试使用PHPickerViewController和可组合体系结构来实现SwiftUI。(我并不认为这是特别相关的,但它可能解释了为什么我的一些代码是这样的)。

样本工程

我一直在玩这个来解决这个问题。我在GitHub上创建了一个小示例项目,它删除了可组合体系结构,并保持UI超级简单。

https://github.com/oliverfoggin/BrokenImagePickers/tree/main

看起来iOS 15在UIImagePickerViewController和PHPickerViewController上都要崩溃了。(这是有意义的,因为他们都在引擎盖下使用相同的UI )。

我想下一步是确定在UIKit应用程序中使用它们时是否会发生相同的错误。

我的代码

我的代码非常直接。这只是使用UIImagePickerViewController的相同特性的重新实现,但我想尝试使用较新的API。

我的密码是这样的..。

代码语言:javascript
复制
public struct ImagePicker: UIViewControllerRepresentable {

// Vars and setup stuff...
  @Environment(\.presentationMode) var presentationMode

  let viewStore: ViewStore<ImagePickerState, ImagePickerAction>
  
  public init(store: Store<ImagePickerState, ImagePickerAction>) {
    self.viewStore = ViewStore(store)
  }
  
// UIViewControllerRepresentable required functions
  public func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> some UIViewController {

    // Configuring the PHPickerViewController
    var config = PHPickerConfiguration()
    config.filter = PHPickerFilter.images
    
    let picker = PHPickerViewController(configuration: config)
    picker.delegate = context.coordinator
    return picker
  }
  
  public func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
  
  public func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
// This is the coordinator that acts as the delegate
  public class Coordinator: PHPickerViewControllerDelegate {
    let parent: ImagePicker
    
    init(_ parent: ImagePicker) {
      self.parent = parent
    }
    
    public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
      picker.dismiss(animated: true)
      
      guard let itemProvider = results.first?.itemProvider,
        itemProvider.canLoadObject(ofClass: UIImage.self) else {
        return
      }
      
      itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
        if let image = image as? UIImage {
          DispatchQueue.main.async {
            self?.parent.viewStore.send(.imagePicked(image: image))
          }
        }
      }
    }
  }
}

所有这些都适用于简单的情况。

我可以呈现ImagePicker视图并选择一张照片,这一切都很好。我可以取消它,好吗?我甚至可以向下滚动我拥有的图像的巨大集合视图。我甚至可以看到新的图像出现在我的状态对象,并显示在我的应用程序。(注.这仍然是WIP,所以代码有点笨重,但这只是为了让它开始工作)。

问题案例

问题是,当我点击PHPickerView中的搜索栏(这是苹果在控件中提供的搜索栏)时,我没有创建它,也没有编写它)。它似乎开始在键盘上滑动,然后视图变成空白,中间只有一条消息.

无法加载照片

再试试

我还得到了一个奇怪的错误日志。(我删除了时间戳,以缩短线条)。

代码语言:javascript
复制
// These happen on immediately presenting the ImagePicker
AppName[587:30596] [Picker] Showing picker unavailable UI (reason: still loading) with error: (null)
AppName[587:30596] Writing analzed variants.


// These happen when tapping the search bar
AppName[587:30867] [lifecycle] [u A95D90FC-C77B-43CC-8FC6-C8E7C81DD22A:m (null)] [com.apple.mobileslideshow.photospicker(1.0)] Connection to plugin interrupted while in use.
AppName[587:31002] [lifecycle] [u A95D90FC-C77B-43CC-8FC6-C8E7C81DD22A:m (null)] [com.apple.mobileslideshow.photospicker(1.0)] Connection to plugin invalidated while in use.
AppName[587:30596] [Picker] Showing picker unavailable UI (reason: crashed) with error: (null)
AppName[587:30596] viewServiceDidTerminateWithError:: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}

点击“重试”按钮重新加载初始滚动屏幕,我可以继续使用它。但是再次点击搜索栏只会显示同样的错误。

我通常是第一个指出这个错误的人,几乎肯定不是Apple的错误,但是这个错误让我很困惑。我不知道我在做什么会导致这种事发生?

是因为它在SwiftUI视图中吗?

在UIKit中重新创建该项目

我用UIKit重做了同一个项目..。https://github.com/oliverfoggin/UIKit-Image-Pickers

我根本无法复制那次坠机。

还有..。如果您正在对设备进行任何类型的屏幕记录,则不会发生崩溃。我试着在设备上录了一段录音,但无法复制。我还试着用iPhone屏幕从我的Mac电脑上录制一段电影,但无法复制崩溃。但是..。当我在QuickTime上停止录音的时候,坠机又被复制了。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2022-02-10 17:27:38

这个为我修复了,就像.ignoreSafeArea(.keyboard)提到的那样。

要详细说明@Frustrated_Student,这个问题与UIViewControllerRepresentable有关,它像对待许多SwiftUI视图一样对待视图,以自动避免键盘。如果您像我一样使用工作表来呈现选择器,那么您可以简单地将.ignoreSafeArea(.keyboard)添加到UIViewControllerRepresentable视图中--在我的例子中--这里称之为ImagePicker是一个更好的例子。

在哪里添加.ignoreSafeArea(.keyboard)

代码语言:javascript
复制
.sheet(isPresented: $imagePicker) {
    ImagePicker(store: store)
        .ignoresSafeArea(.keyboard)
}

这是@Fogmeister代码:

代码语言:javascript
复制
public struct ImagePicker: UIViewControllerRepresentable {

// Vars and setup stuff...
  @Environment(\.presentationMode) var presentationMode

  let viewStore: ViewStore<ImagePickerState, ImagePickerAction>
  
  public init(store: Store<ImagePickerState, ImagePickerAction>) {
    self.viewStore = ViewStore(store)
  }
  
// UIViewControllerRepresentable required functions
  public func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> some UIViewController {

    // Configuring the PHPickerViewController
    var config = PHPickerConfiguration()
    config.filter = PHPickerFilter.images
    
    let picker = PHPickerViewController(configuration: config)
    picker.delegate = context.coordinator
    return picker
  }
  
  public func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
  
  public func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
// This is the coordinator that acts as the delegate
  public class Coordinator: PHPickerViewControllerDelegate {
    let parent: ImagePicker
    
    init(_ parent: ImagePicker) {
      self.parent = parent
    }
    
    public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
      picker.dismiss(animated: true)
      
      guard let itemProvider = results.first?.itemProvider,
        itemProvider.canLoadObject(ofClass: UIImage.self) else {
        return
      }
      
      itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
        if let image = image as? UIImage {
          DispatchQueue.main.async {
            self?.parent.viewStore.send(.imagePicked(image: image))
          }
        }
      }
    }
  }
}
票数 8
EN

Stack Overflow用户

发布于 2021-09-25 10:00:51

好吧..。这似乎是一个iOS错误。

我在这里验证了一个示例项目,它显示了错误.https://github.com/oliverfoggin/BrokenImagePickers

还有一个用UIKit编写的复制项目.https://github.com/oliverfoggin/UIKit-Image-Pickers

我试图对这种情况进行屏幕记录,但是如果有任何屏幕记录正在发生(无论是在设备上还是通过Mac上的QuickTime ),这将抑制错误的发生。

我已经向苹果公司提交了一份雷达,并把这两个项目都发送给了他们,让他们看看正在发生的事情,并提供了很多细节。我会随时更新这方面的任何进展。

无趣的解决办法

经过进一步的研究,我发现您可以从SwiftUI开始,然后在不发生这种崩溃的情况下呈现一个PHPickerViewController。

如果你出示SwiftUI的UIViewControllerRepresentable..。然后从那里开始,如果出现PHPickerViewController,它就不会崩溃。

因此,我想出了一个(非常俗气的)解决办法,以避免这次坠机。

我首先创建一个像包装器一样使用的UIViewController子类。

代码语言:javascript
复制
class WrappedPhotoPicker: UIViewController {
  var picker: PHPickerViewController?
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    if let picker = picker {
      present(picker, animated: false)
    }
  }
}

然后在SwiftUI视图中创建这个包装器并在其中设置选择器。

代码语言:javascript
复制
struct WrappedPickerView: UIViewControllerRepresentable {
  @Environment(\.presentationMode) var presentationMode
  @Binding var photoPickerResult: PHPickerResult?
  
  let wrappedPicker = WrappedPhotoPicker()
  
  func makeUIViewController(context: Context) -> WrappedPhotoPicker {
    var config = PHPickerConfiguration()
    config.filter = .images
    config.selectionLimit = 1
    
    let picker = PHPickerViewController(configuration: config)
    picker.delegate = context.coordinator
    
    wrappedPicker.picker = picker
    return wrappedPicker
  }
  
  func updateUIViewController(_ uiViewController: WrappedPhotoPicker, context: Context) {}
  
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
  
  class Coordinator: PHPickerViewControllerDelegate {
    let parent: WrappedPickerView
    
    init(_ parent: WrappedPickerView) {
      self.parent = parent
    }
    
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
      parent.presentationMode.wrappedValue.dismiss()
      parent.wrappedPicker.dismiss(animated: false)
      
      parent.photoPickerResult = results.first
    }
  }
}

这是远远不理想的,因为我是在错误的时间和东西。但在苹果为这一问题提供永久解决方案之前,它是可行的。

票数 5
EN

Stack Overflow用户

发布于 2022-01-02 12:55:55

在PHPickerViewController崩溃后,我开始得到一个奇怪的UI错误,在那里键盘是不可见的,但我的视图仍然被压缩。所以我怀疑是键盘/回避问题。我在父视图中禁用了键盘避免,并设法阻止它崩溃。

代码语言:javascript
复制
.ignoresSafeArea(.keyboard)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69306179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档