编程iOS 开发人员

在 Swift 中,什么是 ARC?如何在使用闭包和委托时避免保留循环?

用 Hintsage AI 助手通过面试

答案。

ARC(自动引用计数)是一种在 Swift 中的自动内存管理系统。每当一个新强引用指向对象时,计数器增加;删除时减少。当计数器为零时,对象被释放。

保留循环(retain cycle)是指对象之间相互引用强引用,导致它们永远不会被释放的情况。

避免的方法:

  • 对于委托对象,使用弱引用:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
  • 对于闭包,使用 [weak self][unowned self]
class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }

有陷阱的问题。

[weak self][unowned self] 在闭包中有什么区别?在什么情况下使用哪个类型的引用?

答案:

  • [weak self] 创建一个可选引用;self 可能为 nil,因此通常使用安全解包 self?
  • [unowned self] 创建一个非可选引用,并且不会增加计数器;如果对象已经被释放并且发生了访问 — 将崩溃。
  • 选择取决于业务逻辑:如果闭包确保不会比 self 存活得更久,可以使用 [unowned self]

示例:

someClosure = { [weak self] in self?.doTask() } // 或(如果 self 100% 比闭包存活得久): someClosure = { [unowned self] in doTask() }

由于对主题细节不了解而导致的实际错误示例。


故事

在项目中,ViewController 和它的处理点击的闭包之间出现了保留循环。ViewController 引用闭包,该闭包以强引用捕获了 self。结果是,控制器和它的所有数据在关闭屏幕后没有被释放。通过在闭包中引入 [weak self] 解决了这个问题。


故事

在两个对象之间实现委托模式。委托被声明为强(strong)属性。结果在尝试从内存中删除主对象时,它没有被释放,导致内存泄漏。将委托转换为 weak 后,问题消失了。


故事

为动画使用了 UIView 中的闭包。闭包通过 [unowned self] 捕获 self。当在动画完成之前删除视图时,由于访问已释放的 self,应用崩溃。解决方案是使用 [weak self] 并在闭包中强制检查 self 是否为 nil。