iOS 开发每天分享优质文章iOS Developer

JChat Swift 优化 - 本地图片加载篇

2017-10-12  本文已影响527人  YxxxHao

在看这篇文章前,建议先看下面两篇文章:

iOS应用主题(图片,颜色)统一管理

再谈 Swift 换肤功能

最近一直在写公司里的开源项目 JChat ,这里记录下其中优化过程。

本地图片加载的方法

方法名 是否缓存
1. UIImage(named: <#T##String#>) 会一直缓存在内存中
2. UIImage(contentsOfFile: <#T##String#>) 每次都是重新加载

通过方法1来加载图片时,图片会一直缓存在内存中,一般情况不推荐使用这种方式,一个是缓存不可控;第二个图片资源得直接加载到项目中,不方便管理,而且每次添加新图片时工程文件都会变动。

通过方法2来加载图片时,每次都会从硬盘里读图片,这个操作是比较耗时的,文章开头处的两篇文章都是以这个方法来加载图片的。

JChat 优化处理

在 JChat Swift 中,图片资源使用的是 再谈 Swift 换肤功能 一文中的管理方式,就是通过 bundle 来管理图片,这里就不详细说。 上面也说过了,通过 UIImage(contentsOfFile: <#T##String#>) 来访问图片时,每次都需要从硬盘里加载,这样的话,当需要频繁加载图片的时候,通过这种方式去加载图片,就有可能成为性能的瓶颈。

那么我们该如何去优化呢,它的缺点就是没有缓存,这样的话就手动去给它添加缓存,这里直接通过 NSCache 来做就可以:

// 缓存 image 到内存中,提高重复访问的速度
private let memoryCache = NSCache<NSString, UIImage>()

在访问图片资源的时候,如果缓存有该图片,就直接从缓存中返回,如果缓存中不存在,就从硬盘里读,并把读出来的图片缓存起来:

public func loadImage(_ imageName: String, _ style: ThemeStyle) -> UIImage? {

    ....
    
    if let image = memoryCache.object(forKey: name as NSString) {
        return image
    }

    ....
    
    if let imagePath = imagePath {
        image = UIImage(contentsOfFile: imagePath)
    } 
    if let image = image {
        memoryCache.setObject(image, forKey: name as NSString)
    }
    return image
}

这样就搞定了么,显然并没有,虽然这里加了缓存,但还是存在上述方法1中的缓存不可控制问题,当应用内存过高的时候,应用就有可能闪退,所以还得监听系统是否有内存警告:

// 收到内存警告时,移除所有缓存
NotificationCenter.default.addObserver(
    self, selector: #selector(clearMemoryCache), name: .UIApplicationDidReceiveMemoryWarning, object: nil)

如果收到内存警告的时候就把缓存清空:

@objc private func clearMemoryCache() {
    memoryCache.removeAllObjects()
}

这样就可以解决上述方法1和方法2的缺陷了,但需要注意的是,这里的缓存并没有设置数量的上限,因为资源图片本身就比较小,所以占用的空间并不会很大,故没有设置缓存数量的限制。如果需要设置数量限制的话,需要考虑的事情就比较多了,比如说移除时的优先级等,建议是自己实现 cache 的数据结构,这样会更加灵活了,这里就不一一详谈了,可以去看下 YYCache

上一篇下一篇

猜你喜欢

热点阅读