知用网
白蓝主题五 · 清爽阅读
首页  > 生活健康

Swift弱引用和强引用:别让内存问题影响你的App体验

写iOS应用时,Swift内存管理机制常常在背后默默工作。很多人刚开始接触Swift时,对强引用和弱引用的概念有点摸不着头脑,其实这就像人与人之间的关系——有的关系牢不可破,有的则随缘而定。

强引用:牢牢抓住不放手

默认情况下,Swift中的对象引用都是强引用。只要还有一个强引用指向某个对象,这个对象就不会被释放。比如你有个女朋友,她把你的照片放在手机锁屏上,每天打开手机都看到你,那你们的关系大概率很稳固。代码里也一样:

class Person {
    let name: String
    init(name: String) { self.name = name }
}

let xiaoming = Person(name: "小明")
let friend = xiaoming  // 强引用,xiaoming不会被释放

只要friend还存在,xiaoming就不会从内存中消失。

弱引用:轻轻牵手,随时可放

但有些关系不能太“粘人”,不然容易出问题。在iOS开发中,最典型的例子就是代理(delegate)或闭包回调。如果两个对象互相强引用,就会形成循环引用,谁都不肯放手,内存一直占着不放,最终可能导致App变卡甚至崩溃。

这时候就得用weak关键字来建立弱引用。弱引用不会延长对象的生命周期,当对象被释放时,弱引用会自动变成nil。就像朋友之间说“保持联系”,但谁也不强求对方一定得回消息。

class ViewController: UIViewController {
    var label: UILabel?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        label = UILabel(frame: .zero)
        
        // 使用[weak self]避免循环引用
        label?.text = "加载中..."
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
            self?.label?.text = "加载完成"
        }
    }
}

这里用了[weak self],确保闭包不会强持有当前控制器。两秒后即使页面已经关闭,回调也不会导致内存泄漏。

什么时候该用弱引用?

当你发现某个对象只是临时使用另一个对象,或者怕出现“你依赖我、我依赖你”的僵局时,就可以考虑弱引用。常见的场景包括:

  • 闭包中引用self
  • 代理属性(如delegate
  • 父视图和子视图之间的反向引用

比如你写了个自定义按钮,它需要通知控制器按钮被点了,但控制器已经持有了这个按钮。如果按钮又强引用控制器,那就成了“你是我妈,我也是你妈”的逻辑死结。这时按钮里的代理用weak就刚刚好。

小贴士:unowned不是万能替代

除了weak,还有个unowned,它也用于打破循环引用,但更“自信”——它假设对象一直存在。如果对象已经被释放你还去访问,程序就会崩溃。就像坚信前任一定会回头,结果人家早就开始了新生活。所以除非你100%确定对象生命周期更长,否则还是优先选weak

理解强弱引用,不只是为了写对代码,更是为了让App运行更顺畅。就像维持一段健康的关系,有时候懂得适时放手,反而能让彼此更好前行。