iOS 缓存

背景

2016年上半年重构公司APP的时候,发现以前设计是一个Filemanager + Dicttionary,这样存在几个很严重的问题:

  1. Dicttionary存在线程安全问题,多个线程同时写入会crash
  2. Dicttionary虽然有很高的性能,但是无法控制缓存大小
  3. 大文件写入耗时比较长,如果如果是在主线程上会造成卡顿

以前没出现异常,只是因为之前所有的请求解析和存取都是在主线程上串行的,加载的时候完全靠loading覆盖以争取时间

那次重构把机制彻底改了,进入页面异步加载,交互操作也都是异步的,会预先把很多与网络、解析、缓存甚至渲染房贷后台线程并发,期间会大量的读写缓存,给缓存带来很大的压力。

在有限的时间里,我并没有足够的时间去重新设计套缓存,个人也并不太喜欢使用第三方库。相比较NSCache + FileManger, 综合性能和稳定性上来说,是最为可靠的。

在后来的时间里,我读了一下最近比较火的YYCache,只能说作者很聪明: Disk方面,结合File存大文件快,SQLit e存小文件快优势,在相比其他库来说,综合性能确实是有很大的"提升",但是如果全都是大文件,肯定是无法操作FileManager的,而全都是小文件也无法超过SQLite,这是所有复杂设计无法避免的问题,Memory方面提升则不大。

在实际的应用中,存取的文件大小确实不一,但实际应用中也并非一只需要连续的读写,与其花那么大的精力去争取分毫之差,不如在设计、在线程方面来优化,给实际体验带来质的提升。

技巧

  • 通过NSCache的totalCostLimit和countLimit可以控制NSCache开销,不严格,虽然系统会自动管理,但个人建议还是根据实际情况和需求来配置,充分利用性能的同时避免占用太多内存。如果内存暴涨,iOS会强行关闭App的
  • 如果在主线程写缓存,经验做异步线程处理,避免卡顿

应用

充分利用好缓存,能为代码解耦合起到很大的帮助。

在移动端开发中,经常涉及到页面之间的数据交换,iOS有很多种方式来处理:delegate, block, notification, viewModel等等。
但是这些都有很大的不足,delegate需要些大量的协议代码,并且需要被逐个实现。block在处理weak循环引用后,如若对象释放等情况,并不能确保操作生效,notifications与delegate大同小异,甚至在dealloc时还需要确保取消。viewModel相对好一点,但却是单向的。

如果充分利用好Controller生命周期,在适当的位置读取缓存并刷新页面,在合适的时候更新缓存保存状态,这样页面之间几乎不需要任何信息传递,耦合大大减少,同时能确保数据更新是有效的。

class Cache {
    var name:string

    init(key:string) {
        self = readFromDick(key)
    }

    func save {
        encode
        self.wirteToDick
    }
}
class A {
    func updateView {
        var info = cache(info)
        label.text = info.name
    }
    func jumpB {
        push(self)
        present(var b = B())
    }
}
class B {
    func updateName(name:string) {
        var info = cache(info)
        info.name = name
        info.save()
    }

    func popThis{
        pop
    }
}

results matching ""

    No results matching ""