iOS14 中的 UIImagePickerController 和 PHPickerViewController 图像选择空白

Posted

技术标签:

【中文标题】iOS14 中的 UIImagePickerController 和 PHPickerViewController 图像选择空白【英文标题】:UIImagePickerController and PHPickerViewController image selection blank in iOS14 【发布时间】:2020-09-28 02:43:29 【问题描述】:

这在 ios 的最后几个版本上可以正常工作,但在 14 上无法正常工作,过去 5 天我都在谷歌上搜索。

每当我从图库中添加图像时,选择图像的弹出窗口都是空白的。

我已经尝试过 UIImagePickerController(在 iOS13 及以下版本中运行良好)和新的 phpickerViewController。

在 iOS14 之前一直在工作的是用户单击条形按钮以“添加图像”,弹出窗口要求从图库中选择,然后向选择器显示您的图库中的图像。

我已经为 UIImagePickerController 设置了 Info.plist “Privacy - Photo Library Usage Description”,我知道 PHPickerViewController 不需要 perms,因为它会为你处理获取图像。

我也经常看到这些紫色警告说“xxxx 必须仅从主线程使用”,直到新的 Xcode 之前从未见过。

任何帮助将不胜感激。运行Xcode 12.0.1 (12A7300),模拟器运行iOS14。

亚当

class AddCustomExerciseViewController: UIViewController, UITextViewDelegate, UINavigationControllerDelegate, GADBannerViewDelegate, UIImagePickerControllerDelegate, PHPickerViewControllerDelegate

let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler:  _ in self.openGallery() ))
        alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
        self.present(alert, animated: true, completion: nil)

func openGallery()

    let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        switch photoAuthorizationStatus 
        case .authorized:
            self.showGallery()
            print("Access is granted by user")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization(
                (newStatus) in
                print("status is \(newStatus)")
                if newStatus ==  PHAuthorizationStatus.authorized 
                    self.showGallery()
                    print("success")
                
            )
            print("It is not determined until now")
        case .restricted:
            // same same
            print("User do not have access to photo album.")
        case .denied:
            // same same
            print("User has denied the permission.")
        case .limited:
            // same same
            print("User has denied the permission.")
        


func showGallery()

    if #available(iOS 14, *)
    
        var configuration = PHPickerConfiguration()
        configuration.filter = .images
        configuration.selectionLimit = 0
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        self.present(picker, animated: true, completion: nil)
    
    else
    
                
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary)
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.allowsEditing = false
            imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
            self.present(imagePicker, animated: true, completion: nil)
        
        else
        
            let alert  = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        
    

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 
    if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage 
        
        //get the file url
        if let fileUrl = info[UIImagePickerControllerImageURL] as? URL 
            print(fileUrl)
            print(fileUrl.lastPathComponent)
            let filePath = fileUrl.lastPathComponent
            
            if(filePath.hasSuffix("GIF")||filePath.hasSuffix("gif"))
            
                //to change later to support gifs
                gifView.image = pickedImage
            
            else
            
                //to show the static image to users
                gifView.image = pickedImage
            
            //for saving the file name to retrieve in local parse datastore
            imageNameToSave = fileUrl.lastPathComponent
        
        //for saving the selected image
        imageToSave = pickedImage
    
    picker.dismiss(animated: true, completion: nil)

@available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])

   picker.dismiss(animated: true, completion: nil)
   for result in results
   
      result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler:  (object, error) in
         if let image = object as? UIImage 
            DispatchQueue.main.async 
               // Use UIImage
               print("Selected image: \(image)")
            
         
      )
   
  

【问题讨论】:

嗨亚当,你找到任何解决方案了吗?我遇到了几乎相同的问题,我可以获取图像列表,但我无法选择并获取错误,因为`-[NSURL URLByAppendingPathExtension:]:组件、组件或路径扩展不能为 nil。` 嗨@Hindu,我在回复一个答案时写道,它似乎只是有错误的模拟器。我在几个真正的 iOS 设备上尝试过,画廊打开了,我可以很好地选择一张图片。 有人找到解决方案了吗?我有同样的问题。 UIPickerViewController 和 PHPickerViewController 都出现在 iOS14 中,并且会在相册视图中显示相册,但即使您选择相册,照片选择视图中也不会显示照片。我的 iPhone 也试过了,还是不行。 【参考方案1】:

在 iOS 14 上,受限图像选择器权限对话框在单独的线程中打开,因此当授权返回时,您需要在主线程上执行 UI 任务。

PHPhotoLibrary.requestAuthorization(
        (newStatus) in
    DispatchQueue.main.async 
        print("status is \(newStatus)")
        if newStatus ==  PHAuthorizationStatus.authorized 
            self.showGallery()
            print("success")
        
    
)

【讨论】:

谢谢,我已经添加了 DispatchQueue.main.async ,就像您在上面显示的那样,它消除了紫色警告并在主线程上运行,但我仍然无法浏览照片画廊。 为什么是configuration.selectionLimit = 0,这是一次可以选择的照片数量,你可以试试configuration.selectionLimit = 1 selectionLimit = 0 等于无限选择。我确实尝试了= 1,但没有任何区别。见这里:mackuba.eu/2020/07/07/photo-library-changes-ios-14 随后我在真实的 iOS14 设备上做了一些测试,我上面的代码工作得很好,它似乎在模拟器中。我将更新发布到应用商店,并一直在朋友的设备上试用,一切正常。 gymexercisesapp.com【参考方案2】:

如果这对其他人有帮助,我发现编辑滚动视图外观代理背景会导致 UIImagePickerController 和 PHPickerViewController 出现错误,从而阻止它们在 iOS 14 及更高版本中显示图像。我编辑了滚动视图背景代理,因为即使在浅色模式下它也是黑色的。经过数小时的谷歌搜索和测试,我发现删除滚动视图代理上的外观背景修改允许图像选择器按预期运行。我向 Apple 提交了错误报告。导致该错误的代码行是:

UIScrollView.appearance().backgroundColor = .systemBackground

【讨论】:

以上是关于iOS14 中的 UIImagePickerController 和 PHPickerViewController 图像选择空白的主要内容,如果未能解决你的问题,请参考以下文章

iOS14中表格部分标题中的白色背景

如何更改 SwiftUI 和 iOS 14 中的单元格背景颜色?

UIImagePickerController 不会停止位置服务

Xcode 12 和 iOS 14 中的手势问题

无法再与 iOS 14 中的 UICollectionViewCell 或 UITableViewCell 中的内容进行交互 [重复]

移动 Chrome 中的 webRTC,iOS 版本低于 14.3