无主引用(unowned)
声明属性或者变量时,在前面加上unowned关键字表示这是一个无主引用,无主引用不能设置为nil,因为非可选类型的变量不允许被赋值为nil。
两个属性,其中一个为可选类型,另外一个不是可选类型,而且相互引用,这种情况下一般使用无主引用去解决循环强引用。
案例
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit { print("\(name) is being deinitialized") }
}
复制代码
class CreditCard {
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
复制代码
注意
CreditCard
类的number
属性被定义为UInt64
类型而不是Int
类型,以确保number
属性的存储量在 32 位和 64 位系统上都能足够容纳 16 位的卡号。
下面的代码片段定义了一个叫john
的可选类型Customer
变量,用来保存某个特定客户的引用。由于是可选类型,所以变量被初始化为nil
: var john: Customer?
现在你可以创建Customer
类的实例,用它初始化CreditCard
实例,并将新创建的CreditCard
实例赋值为客户的card
属性:
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
复制代码
在你关联两个实例后,它们的引用关系如下图所示:
Customer
实例持有对 CreditCard
实例的强引用,而 CreditCard
实例持有对 Customer
实例的无主引用。
由于 customer
的无主引用,当你断开 john
变量持有的强引用时,再也没有指向 Customer
实例的强引用了:
Customer
实例的强引用,该实例被销毁了。其后,再也没有指向
CreditCard
实例的强引用,该实例也随之被销毁了:
john = nil
// 打印 “John Appleseed is being deinitialized”
// 打印 ”Card #1234567890123456 is being deinitialized”
复制代码
最后的代码展示了在john
变量被设为nil
后Customer
实例和CreditCard
实例的构造函数都打印出了“销毁”的信息。
注意 上面的例子展示了如何使用安全的无主引用。对于需要禁用运行时的安全检查的情况(例如,出于性能方面的原因),Swift还提供了不安全的无主引用。与所有不安全的操作一样,你需要负责检查代码以确保其安全性。 你可以通过unowned(unsafe)来声明不安全无主引用。如果你试图在实例被销毁后,访问该实例的不安全无主引用,你的程序会尝试访问该实例之前所在的内存地址,这是一个不安全的操作。
引自:http://www.piggybear.net/?p=681