乐闻世界logo
搜索文章和话题

Swift 中的内存管理机制是什么?如何避免循环引用?

2月21日 14:23

Swift 中的内存管理机制是什么?什么是 ARC(自动引用计数)?如何避免循环引用?

Swift 使用自动引用计数(ARC)来自动管理应用程序的内存。ARC 会跟踪和管理应用程序使用的内存,并在实例不再需要时自动释放内存。

ARC 的工作原理:

  • 每次创建类实例的新引用时,ARC 会增加该实例的引用计数
  • 当引用被移除时,ARC 会减少引用计数
  • 当引用计数降为零时,ARC 会释放该实例的内存
  • ARC 只适用于类类型的实例,结构体和枚举是值类型,不参与引用计数

强引用循环:

  • 两个或多个类实例相互持有强引用,导致引用计数永远不会降为零
  • 常见场景:类之间的相互引用、闭包捕获类实例
  • 示例:
    swift
    class Person { var apartment: Apartment? } class Apartment { var tenant: Person? } let person = Person() let apartment = Apartment() person.apartment = apartment apartment.tenant = person

解决循环引用的方法:

  1. 弱引用:

    • 使用 weak 关键字声明
    • 不会增加引用计数
    • 引用的对象被释放后,弱引用会自动变为 nil
    • 必须声明为可选类型
    • 适用于引用可能为 nil 的情况
    • 示例:
      swift
      class Apartment { weak var tenant: Person? }
  2. 无主引用:

    • 使用 unowned 关键字声明
    • 不会增加引用计数
    • 引用对象被释放后,无主引用不会自动变为 nil
    • 不能声明为可选类型
    • 适用于引用对象生命周期更长的情况
    • 示例:
      swift
      class Customer { let creditCard: CreditCard init(creditCard: CreditCard) { self.creditCard = creditCard } } class CreditCard { unowned let customer: Customer }
  3. 闭包中的循环引用:

    • 使用捕获列表 [weak self][unowned self]
    • 示例:
      swift
      class HTMLElement { let name: String lazy var asHTML: () -> String = { [weak self] in guard let self = self else { return "" } return "<\(self.name)>" } }

最佳实践:

  1. 在类属性中使用 weakunowned 避免强引用循环
  2. 在闭包中使用捕获列表处理循环引用
  3. 使用 weak 当引用可能为 nil 时
  4. 使用 unowned 当引用对象生命周期更长时
  5. 使用 Instruments 工具检测内存泄漏
标签:Swift