写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运行更顺畅。就像维持一段健康的关系,有时候懂得适时放手,反而能让彼此更好前行。