iOS 8 从 PHAsset 快速加载图像

Posted

技术标签:

【中文标题】iOS 8 从 PHAsset 快速加载图像【英文标题】:iOS 8 Load Images Fast From PHAsset 【发布时间】:2014-12-10 18:35:13 【问题描述】:

我有一个应用程序可以让人们组合最多 4 张图片。但是,当我让他们从他们的照片中选择(最多 4 张)时,即使我将图像质量设置为 FastFormat,它也会非常慢。这将需要 4 秒(每张照片约 1 秒)。在最高质量下,4 张图像需要 6 秒。

您能否建议我更快地获取图像?

这是我处理图像的块。

func processImages()
    
        _selectediImages = Array()
        _cacheImageComplete = 0
        for asset in _selectedAssets
        
            var options:PHImageRequestOptions = PHImageRequestOptions()
            options.synchronous = true
            options.deliveryMode = PHImageRequestOptionsDeliveryMode.FastFormat
            PHImageManager.defaultManager().requestImageForAsset(asset, targetSize:CGSizeMake(CGFloat(asset.pixelWidth), CGFloat(asset.pixelHeight)), contentMode: .AspectFit, options: options)
                
                    result, info in
                    var minRatio:CGFloat = 1
                    //Reduce file size so take 1/3 the screen w&h
                    if(CGFloat(asset.pixelWidth) > UIScreen.mainScreen().bounds.width/2 || CGFloat(asset.pixelHeight) > UIScreen.mainScreen().bounds.height/2)
                    
                        minRatio = min((UIScreen.mainScreen().bounds.width/2)/(CGFloat(asset.pixelWidth)), ((UIScreen.mainScreen().bounds.height/2)/CGFloat(asset.pixelHeight)))
                    
                    var size:CGSize = CGSizeMake((CGFloat(asset.pixelWidth)*minRatio),(CGFloat(asset.pixelHeight)*minRatio))
                    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
                    result.drawInRect(CGRectMake(0, 0, size.width, size.height))
                    var final = UIGraphicsGetImageFromCurrentImageContext()
                    var image = iImage(uiimage: final)
                    self._selectediImages.append(image)
                    self._cacheImageComplete!++
                    println(self._cacheImageComplete)
                    if(self._cacheImageComplete == self._selectionCount)
                    
                        self._processingImages = false
                        self.selectionCallback(self._selectediImages)
                    
            

        
    

【问题讨论】:

这可能有助于实现您所需要的,而无需付出更多努力。看看 ios 代码无需运行 React Native 代码:***.com/questions/49305438/… 【参考方案1】:

不要自己调整图像的大小——PHImageManager 的部分目的就是为你做这件事。 (它还缓存缩略图,以便您下次可以更快地获取它们,并在应用程序之间共享该缓存,这样您就不会最终有六个应用程序为您的整个库创建六个单独的 500MB 缩略图缓存。 )

func processImages() 
    _selectediImages = Array()
    _cacheImageComplete = 0
    for asset in _selectedAssets 
        let options = PHImageRequestOptions()
        options.deliveryMode = .FastFormat

        // request images no bigger than 1/3 the screen width
        let maxDimension = UIScreen.mainScreen().bounds.width / 3 * UIScreen.mainScreen().scale
        let size = CGSize(width: maxDimension, height: maxDimension)

        PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: size, contentMode: .AspectFill, options: options)
             result, info in
                // probably some of this code is unnecessary, too,
                // but I'm not sure what you're doing here so leaving it alone
                self._selectediImages.append(result)
                self._cacheImageComplete!++
                println(self._cacheImageComplete)
                if self._cacheImageComplete == self._selectionCount 
                    self._processingImages = false
                    self.selectionCallback(self._selectediImages)
                
            
        
    

显着变化:

不要在主线程上同步请求图像。只是不要。 将正方形最大尺寸传递给requestImageForAsset 并使用AspectFill 模式。无论长宽比如何,这都会为您提供一个裁剪以填充该正方形的图像。 您在此处按像素大小要求图像,屏幕大小以磅为单位。乘以屏幕比例,否则您的图像将被像素化。 (再说一次,你要求FastFormat,所以无论如何你可能会得到模糊的图像。)

【讨论】:

非常感谢您的额外说明。我将在周末浏览我的整个应用程序并将所有内容更改为缩放像素。我现在就试试这个【参考方案2】:

你为什么说synchronous?显然,这会使事情慢下来。而且,绝对禁止在主线程上说synchronous!!!!阅读文档并遵守它们。这是这里的主要问题。

还有许多其他考虑因素。基本上你使用这个调用都是错误的。一旦你删除了synchronous,不要这样处理图像!请记住,此回调将被调用多次,因为图像提供的版本越来越好。你不能在这里做任何耗时的事情。

(另外,你为什么要调整图像的大小?如果你想要某个尺寸的图像,你应该在请求时要求该尺寸。让图像获取器为你完成工作。)

【讨论】:

我刚开始打aysnc电话。但是关于图像大小,问题是这样的:***.com/questions/26660534/… 您知道获得较小图像的更好方法吗? 请不要偷懒。我已经解释了缓慢的原因:您在主线程上说synchronous。那是你问的。如果您还有其他问题,请提出其他问题。 你能回答我上面发的那个吗? 我在这里给出的答案有什么问题? image-fetcher 可以让你指定一个合理的显示尺寸。请记住,您的 UI 只是您的 UI。除非用户批准对照片进行编辑,否则您无需使用真实图像。

以上是关于iOS 8 从 PHAsset 快速加载图像的主要内容,如果未能解决你的问题,请参考以下文章

从 PHAsset 加载图像非常慢

iOS 8 照片框架:从 PHAsset 获取文件名

如何从 PHAsset for iOS 13 获取图像 url

从 iOS 8 中的 PHAsset 获取文件扩展名?

照片框架 - 如何从 PHAsset 获取图像的 CLLocation?

快速检测从照片库中删除的图像