从 iCloud 获取图像将冻结 UI

Posted

技术标签:

【中文标题】从 iCloud 获取图像将冻结 UI【英文标题】:Fetch Images From ICloud Will Freeze The UI 【发布时间】:2018-03-03 16:22:06 【问题描述】:

我正在使用 BSImagePicker 库在我的应用程序中选择多个图像,当用户选择存储在 ICloud 上的图像时,UI 将冻结在图像选择器控制器上,直到图像被下载我尝试修复它但没有结果

这是我的代码:

选择图片并在滑块中显示

 @IBAction func choose_images(_ sender: Any) 

        bs_presentImagePickerController(vc, animated: true,
                                        select:  (asset: PHAsset) -> Void in
                                            // User selected an asset.
                                            // Do something with it, start upload perhaps?
        , deselect:  (asset: PHAsset) -> Void in
            // User deselected an assets.
            // Do something, cancel upload?
        , cancel:  (assets: [PHAsset]) -> Void in

        , finish:  (assets: [PHAsset]) -> Void in
            // User finished with these assets

            // print(assets.count)

            DispatchQueue.main.async
                self.imagesource.removeAll()
                self.imagesdata.removeAll()
                for img in assets

                    self.imagesource.append(ImageSource(image:  self.getUIImage(asset: img)!))
                    self.imagesdata.append(self.getUIImage(asset: img)!)
                

                self.slider.setImageInputs(self.imagesource)
                self.slider.contentScaleMode = UIViewContentMode.scaleAspectFill
                self.slider.slideshowInterval = 2
                self.slider.zoomEnabled = true
                self.slider.backgroundColor = UIColor.black
                self.slider.pageControlPosition = PageControlPosition.insideScrollView
                let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.didTap))
                self.slider.addGestureRecognizer(recognizer)
            
        , completion: nil)


    

返回所选资产图像的功能

func getUIImage(asset: PHAsset) -> UIImage? 

        var img: UIImage?
        let manager = PHImageManager.default()
        let options = PHImageRequestOptions()
        options.version = .original
        options.isNetworkAccessAllowed = true
        options.isSynchronous = true
        options.progressHandler =  (progress, error, stop, info) in
            if(progress == 1.0)
                SVProgressHUD.dismiss()
             else 

                SVProgressHUD.showProgress(Float(progress), status: "Downloading from iCloud")

            
        
        manager.requestImage(for: asset, targetSize:PHImageManagerMaximumSize, contentMode: PHImageContentMode.aspectFit, options: options)  (image, info) in

            img = image
        

        return img
    

任何帮助将不胜感激

【问题讨论】:

为什么要同步访问主队列上的远程资源? 如果我将 options.isSynchronous 设置为 false 它将返回 nil ! 当然因为它是异步的,并且您的代码被正确编写以处理异步。 @rmaddy 请解释一下我应该在我的代码中更改什么 你在哪里使用 self.imagesdata? 【参考方案1】:

您的主要问题是您正在同步访问主队列上的远程图像。您需要在后台执行循环。

您需要更新finish 块中的代码,如下所示:

, finish:  (assets: [PHAsset]) -> Void in
    DispatchQueue.global().async 
        self.imagesource.removeAll()
        self.imagesdata.removeAll()
        for img in assets 
            if let res = getUIImage(asset: img) 
                self.imagesource.append(ImageSource(image: res))
                self.imagesdata.append(res)
            
        

        DispatchQueue.main.async 
            self.slider.setImageInputs(self.imagesource)
            self.slider.contentScaleMode = UIViewContentMode.scaleAspectFill
            self.slider.slideshowInterval = 2
            self.slider.zoomEnabled = true
            self.slider.backgroundColor = UIColor.black
            self.slider.pageControlPosition = PageControlPosition.insideScrollView
            let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.didTap))
            self.slider.addGestureRecognizer(recognizer)
        
    

您可能还必须更新 getUIImage 内的进度处理程序,以更新主队列上的 SVProgressHUD。

请注意,除了我刚才提到的一项更改之外,您应该保持您的getUIImage 原样使用上述代码。

【讨论】:

【参考方案2】:

只需尝试替换以下代码

for img in assets

    self.imagesource.append(ImageSource(image:  self.getUIImage(asset: img)!))
    self.imagesdata.append(self.getUIImage(asset: img)!)

用这个:

for img in assets
     let image = self.getUIImage(asset: img)!
     self.imagesource.append(ImageSource(image: image))
     self.imagesdata.append(image)

【讨论】:

虽然这是一个很好的改变,但这并不会改变所有图像加载都在主队列上同步完成的事实。

以上是关于从 iCloud 获取图像将冻结 UI的主要内容,如果未能解决你的问题,请参考以下文章

如何快速获取 iCloud 图片 URL

如何将调色板图像从另一个线程生成到 WPF UI 线程?

如何获取存储在 iCloud 中的图像路径?

从 iCloud 打开 txt 文件

从 iCloud Drive iOS 目标 C 下载图像

从firebase数据库中获取添加的孩子,它冻结了用户界面