IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    swift 中内存狂飙的问题

    R0uter发表于 2016-11-28 16:24:36
    love 0

    去落格博客阅读完整排版的swift 中内存狂飙的问题

    在使用 Swift 语言进行开发的时候,很多朋友会莫名奇妙地遇到内存爆满的问题,明明有 ARC ,明明释放了内存,却还是让程序的内存占用随着循环而一路飙升。

    这里其实并不是出现了内存泄露,这其实是 ARC 的一个机制:在每一个主 Runloop 结束的时候进行清理。也就是说,它有一套必要的缓存机制——毕竟,实时释放的话谁能保证你的局部变量要不要留下来给后续的代码使用呢?

    但显然,这个必要的机制在这个时候成了我们的噩梦,比如说:

    func test() {
        for _ in 0..<999 {
            let a = loadBigData()
        }
    }

    这里我们假定这个

    loadBigData()
     是一个加载文件略大又费事的动作,那么按照想法,这个文件在每次循环都会被释放——毕竟是个循环内的局部变量,但实际上由于 ARC 的缓存机制,内存就会一直变大。

    软件内存占用一直增大直到卡死系统
    软件内存占用一直增大直到卡死系统

    这个时候,我们可以说 ARC 并不是很智能,所以一旦遇到这种情况,那么就需要人工对 ARC 进行干预,来达到更好的内存管理效果。

    在 Swift 中,我们使用这个全局函数

    public func autoreleasepool<Result>(invoking body: () throws -> Result) rethrows -> Result

    可以看到,它是一个泛型声明,返回的类型根据你传入的闭包而定。我们要做的就是将需要计算的内容放入这个函数中进行计算,这样就相当于是临时把为这个内容开放的内存标记为不要缓存,那么 ARC 不会等到 Runloop 结束才回收,而是在用完后立即回收内存资源,比如说改成这样:

    func test() {
        for _ in 0..<999 {
            autoreleasepool {
                let a = loadBigData()
            }
        }
    }

    这样,计算完成的内容就会立即被清理掉,程序的行为才真正符合我们的本意。

    内存稳定在可控的范围
    内存稳定在可控的范围

    最后还是要补一句,这里我们的

    loadBigData()
     指代的是一个加载大文件然后获取想要的数据再返回的过程,并非初始化一个类,如果是通过类初始化比如
    Dafa(URL:url)
     这样的初始化方法,ARC 是能够自动管理的。这里我们讨论的是一种非常特殊的情况——毕竟大家编程这么久,也并不一定会碰到几次。

    swift 中内存狂飙的问题,首发于落格博客。

    其他推荐:
    1. 在 Swift 里使用 SQLite 数据库
    2. Swift 里的 Stack 实现
    3. 一道 华为 面试 的 编程算法 题
    4. Swift 开发者的 SDK
    5. Swift 使用 InputMethodKit 写输入法



沪ICP备19023445号-2号
友情链接