iOS 大图显示

问题

对于超高分辨率的图片读取存在内存暴涨甚至崩溃的问题, 特别是对于 tableView 中多张图片同时读取的场景.

原因

这里有几篇分析文章
WWDC2018-图像最佳实践 Image and Graphics Best Practices
iOS中的图片使用方式、内存对比和最佳实践
iOS 深入分析大图显示问题

其中第一篇来自 WWDC2018, 它给出了我们最佳的大图显示方式

我们可以从中得到内存暴涨是因为 图片显示前的 decode 操作.

实践

这里来自 WWDC 的代码:

 func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
        let sourceOpt = [kCGImageSourceShouldCache : false] as CFDictionary
     
        let source = CGImageSourceCreateWithURL(imageURL as CFURL, sourceOpt)!
        
        let maxDimension = max(pointSize.width, pointSize.height) * scale
        let downsampleOpt = [kCGImageSourceCreateThumbnailFromImageAlways : true,
                             kCGImageSourceShouldCacheImmediately : true ,
                             kCGImageSourceCreateThumbnailWithTransform : true,
                             kCGImageSourceThumbnailMaxPixelSize : maxDimension] as CFDictionary
        let downsampleImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOpt)!
        return UIImage(cgImage: downsampleImage)
    }

此处需注意两个选项的设置:
1.kCGImageSourceShouldCache此处设为false,目的在于告知系统此imageSource仅为建立与imageURL的链接,不需要解码。
2.kCGImageSourceShouldCacheImmediately设为true,以此控制系统以计算出的size创建Image Buffer并解压。

为了解决 decode 导致的内存暴涨问题, 在 decode 前创建缩略图,对图片进行预处理(缩小解码后 imageBuffer 的 size),从而降低内存占用.
具体分析可以参见 WWDC2018-图像最佳实践 Image and Graphics Best Practices

使用

let url = URL(string: "http://upload-images.jianshu.io/upload_images/565029-013002ee76523276.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240")
       let image = downsample(imageAt: url!, to: CGSize(width:564, height:564), scale: 1.0)
       imageView.image = image

这里值得说明的是, downsample(:) 中 imageURL 参数可以是网络/本地 URL

至于在列表中的使用方式 WWDC2018-图像最佳实践 Image and Graphics Best Practices
一文中也有介绍

你可能感兴趣的:(iOS 大图显示)