Swift学习48:ARC

张建 lol

ARC

  • swift 使用 自动引用计数(ARC) 来跟踪并管理应用使用的 内存

  • 引用计数 只应用在 的实例。

  • 结构体和枚举 都是 值类型,并非引用类型,不是以引用的方式来 存储和传递

ARC 如何工作

  • 每次创建一个类的实例,ARC 就会分配一个内存块,用来存储这个实例的相关信息。这个内存块保存着实例的类型,以及这个实例相关的属性的值

  • 当实例不再被使用时,ARC 是否这个实例使用的内存,使这块内存可做它用。保证了实例不再被使用时,不会占用内存空间

  • 但是,如果 ARC 释放了仍在使用的实例,那么你就不能再访问这个实例的苏醒或者调用它的方法。如果你仍然视图访问这个实例,应用极有可能会崩溃

  • 为了保证不会发生上述的情况, ARC 跟踪类实例的相关属性、常量及变量的数量。只要有一个有效的引用,ARC 都不会释放这个实例

  • 为了让这个变成现实,只要你将一个类的实例赋值给一个属性或常量或变量,这个属性、常量、变量就是这个实例的 强引用(strong reference)。之所以称之为 强引用,是因为它持有这实例,并且只要这个强引用还存在,就不能销毁实例

循环引用

  • 在两个类实例彼此保持对方的强应用,使得每个实例都使对方保持有效时会发生这种情况。我们称之为强引用环

  • 通过用 弱引用或者无主引用取代强引用,我们可以 解决强引用环问题

解决循环引用

  • 弱引用和无主引用 允许引用环中的一个实例引用另外一个实例,但 不是强引用。因此实例可以互相引用但是不会产生强引用

    • 弱引用不会增加实例的引用计数,因此不会阻止ARC销毁被引用的实例。这种特性使得引用不会编程强引用环。声明属性或者变量的时候,关键字 weak 表明引用为弱引用。

    • 弱引用只能声明为变量类型,因为运行时它的值可能会变。弱引用绝对不能声明为常量

    • 因为弱引用可以没有值,所以声明弱引用的时候 必须是可选类型 的。在swift语言中,推荐使用可选类型作为可能没有值的引用类型

1
2
3
var person: Person?

weak var student: Student?
  • 对于生命周期中引用会变nil的实例,使用弱引用;对于初始化时赋值之后引用再也不会赋值为nil的实例,使用无主引用

    • 和弱引用相似,无主引用 也不强持有实例。但是和弱引用不同的是,无主引用默认始终有值。因此,无主引用只能定义为非可选类型。在属性、变量前添加 unowned 关键字,可以声明一个无主引用

    • 因为是 可选类型,因此当使用无主引用时,不需要展开,可直接访问。不过非可选类型变量不能赋值为 nil,因此当实例被销毁的时候,ARC无法将引用赋值为 nil

    • 当实例被销毁后,试图访问该实例的无主引用会触发运行时错误。使用无主引用时请确保引用始终指向一个未销毁的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
class City {
// 无主引用
unowned let country: Country
init(country: Country) {
self.country = country
}
}
class Country {
var capitaCity: City!
init(capitaCity: City) {
self.capitaCity = capitaCity
}
}

闭包引用循环

将一个闭包赋值给类实例的某个属性,并且这个闭包使用了实例,这样也会产生强引用环。这个闭包可能反问了实例的某个属性,如果 self.someProperty,或者调用了实例的某个方法 self.someMethod。这两种情况都导致了闭包使用 self,从而产生了循环引用

解决:

  • 定义占有列表-占有列表中的每个元素都是由 weak 或者 unowend 关键字和实例的引用(如 selfsomeInstance)组成。每一对都在括号中,通过逗号分开

  • 当闭包和占有的实例总是互相引用时并且总是同时销毁时,将闭包内的占有定义为无主引用

  • 相反的,当占有引用有时可能会是 nil 时,将闭包内的占有定义为 弱引用

1
2
3
4
5
6
lazy var someClosure = {
[unowned self, weak delete = self.delete]
(index: Int,stringToProcess: String) -> String in

// closure body goes here
}
  • Post title:Swift学习48:ARC
  • Post author:张建
  • Create time:2023-03-13 17:44:18
  • Post link:https://redefine.ohevan.com/2023/03/13/Swift课程/Swift学习48:ARC/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.