15、Swift的自动引用计数

Swift的自动引用计数

  • ARC
  • ARC是如何工作的
  • 循环引用
  • 解决循环引用
    • 弱引用
    • 无主引用
  • 闭包引起的循环引用
    • 闭包引用循环解决

ARC

  • Swift使用自动引用计数(ARC)来跟踪并管理应用使用的内容。当实例不被使用时,ARC会自动释放这些类的实例所占用的内存。
  • 引用计数只应用在类的实例。结构体和枚举类型都是值类型,并非引用类型,不是以引用类型的方式来存储和传递的。

ARC是如何工作的

  • 每次创建一个类的实例,ARC都会分配一个内存块,用来存储这个实例的相关信息。这个内存块保存着实例的类型,以及这个实例相关的属性的值。
  • 当实例不在被使用时,ARC会释放这个实例使用的内存空间。
  • 但是如果ARC释放了仍在使用的实例,那么你就不能再访问这个实例的属性和方法。如果你仍然在试图访问这个实例,有可能会崩溃
  • 为了保证不会发生上述情况,ARC跟踪与类的实例相关的属性、常量以及变量的数量。只要有一个有效的引用,ARC都不会释放这个实例。
  • 只要你将一个类的实例赋值给一个属性或者常量或者变量,这个属性、常量或者变量就是这个实例的强引用。之所以称为强引用,是因为它强持有这个实例,并且只要这个强引用还在,实例就不能被销毁。

循环引用

  • 在两个类实例彼此保持对方的强引用,使得每个实例都使对方保持有效时会发生这种情况。
  • 通过弱引用或者无主引用来取代强引用,可以解决强引用引起的循环引用。
    15、Swift的自动引用计数_第1张图片
class Person {
     
    let name:String
    init(name:String){
     
        self.name = name
    }
    var department:Apartment?
    deinit {
     
        print("\(name) is being deinitialized")
    }
}

class Apartment {
     
    let unit:String
    init(unit:String){
     
        self.unit = unit
    }
    var tenant:Person?
    deinit {
     
        print("Apartment \(unit) is being deinitialized")
    }
}

解决循环引用

  • 弱引用和无主引用允许引用环中的一个实例引用另外一个实例,但是不是强引用。因此实例可以相互引用但是不会产生强引用环。
  • 对于生命周期中引用会变为nil的实例,使用弱引用;对于初始化时赋值之后再也不会赋值为nil的实例,使用无主引用。

弱引用

  • 弱引用不会增加实例的引用计数,因此不会阻止ARC销毁被引用的实例。这种特性使得引用不会变成强引用环。声明属性或者变量的时候,关键字weak表明引用为弱引用。
  • 弱引用只能声明变量类型,因为运行时它的值是可以改变的。弱引用绝对不能声明为常量。
  • 因为弱引用可以没有值,所以声明弱引用的时候必须是可选的。在Swift语言中,推荐使用可选类型来作为可能没有值的引用的类型。
 weak var tenant:Person?

无主引用

  • 无主引用默认始终有值。因此,无主引用只能定义为非可选类型。在属性。变量前添加unowned关键字,可以声明一个无主引用。
  • 因为是非可选类型,因此当使用无主引用的时候,不需要展开,可以直接访问。不过非可选类型变量不能赋值为nil,因此当实例对象销毁的时候,ARC无法将引用赋值为nil。
  • 当实例被销毁后,试图访问该实例的无主引用会触发运行时错误。使用无主引用时请确保引用始终指向故意未销毁的实例。
 unowned var countty:Country

闭包引起的循环引用

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

闭包引用循环解决

定义占有列表-占有列表中的每个元素都是由weak或者unowned关键和实例的引用(如self或者someInstance)组成。每一对都在中括号,通过逗号隔开。
当闭包和占有的实例总是相互引用并且总是同时销毁时,将闭包内的占有定义为无主引用。
相反的,当占有引用可能会是nil,将闭包内的占有引用定义为弱引用。

   lazy var someClosure = {
     
        [unowned self,weak delegate = self.delegate] (index:Int,stringToProcess:String) in
        //
    }

你可能感兴趣的:(Swift,1024程序员节)