swift自动引用计数

106 阅读3分钟

1.自动引用计数实践

  • ARC 初始化

    var reference1: Person?
    var reference2: Person?
    var reference3: Person?
    reference1 = Person(name: "John Appleseed")
    reference2 = reference1
    reference3 = reference1
    reference1 = nil
    reference2 = nil  //   此时person对象还没有释放,
    reference3 = nil  // 执行之后,对象进行释放,打印deinit 方法
    // 打印 “John Appleseed is being deinitialized
    

2.类实例之间的循环强引用

  • Person 和Apartment

3.解决实例之间的循环强引用 --- 弱引用(weak reference)

  • Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:弱引用(weakreference)和无主引用(unownedreference )

4.解决实例之间的循环强引用 --- 无主引用(unowned reference )

  • 在前面加上关键字unowned表示这是一个无主引用
  • Person和Apartment的例子展示了两个属性的值都允许为nil,并会潜在的产生循环强引用。这种场景最适合用弱引用来解决。
  • Customer和CreditCard的例子展示了一个属性的值允许为nil,而另一个属性的值不允许为nil,这也可能会产生循环强引用。这种场景最适合通过无主引用来解决。

5.无主引用以及隐式解析可选属性

  • 在这种场景中,两个属性都必须有值,并且初始化完成后永远不会为nil。在这种场景中,需要一个类使用无主属性,而另外一个类使用隐式解析可选属性
  • Country的构造函数调用了City的构造函数。然而,只有Country的实例完全初始化后,Country的构造函数才能把self传给City的构造函数
  • 为了满足这种需求,通过在类型结尾处加上感叹号(City!)的方式,将Country的capitalCity属性声明为隐式解析可选类型的属性。这意味着像其他可选类型一样,capitalCity属性的默认值为nil,但是不需要展开它的值就能访问它
  • 由于capitalCity默认值为nil,一旦Country的实例在构造函数中给name属性赋值后,整个初始化过程就完成了。这意味着一旦name属性被赋值后,Country的构造函数就能引用并传递隐式的self。Country的构造函数在赋值capitalCity时,就能将self作为参数传递给City的构造函数

6.闭包引起的循环强引用

  • Swift 提供了一种优雅的方法来解决这个问题,称之为闭包捕获列表(closure capture list)

  • 定义了一个类,一个懒加载属性,懒加载属性是个闭包,内部强引用了类的2个属性

  • 实例化对象

  • 实例和闭包的引用关系如下:

7.解决闭包引起的循环强引用

  • 在定义闭包时同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用

  • 捕获列表中的每一项都由一对元素组成,一个元素是weak或unowned关键字,另一个元素是类实例的引用(例如self)或初始化过的变量(如delegate = self.delegate!)。这些项在方括号中用逗号分开

    lazy var someClosure: (Int, String) -> String = {
        [unowned self, weak property= self. property!] (index: Int, stringToProcess: String) -> String in
        // 这里是闭包的函数体
    } 
    

8.使用弱引用和无主引用

  • 在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用。
  • 相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查它们是否存在。
  • 注意如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。