自动引用计数(ARC)主要用来跟踪和管理应用程序的内存,通常不需要手动维护,我这里只是记录三个官方例子的使用场景
循环强引用
使用场景:当一个人和一个房间互相绑定的时候,假设需要注销某一对象的时候,因为资源还在互相占用,会出现无法注销的情况
引起问题: 编译型语言与脚本语言不同,执行完后不会直接注销,即使手动注销实例,即使手动注销实例也不会生效,造成内存泄露
class Person{
let name: String
var apartment: Apartment?
init(name: String){
self.name = name
}
deinit{
print("\(self.name) is begin deinitialized")
}
}
class Apartment{
let unit: String
weak var tenant: Person?
init(unit: String){
self.unit = unit
}
deinit {
print("Aparment \(unit) is begin deinitialized")
}
}
以上代码中, 假设将4A房间
绑定给john
,同时将john
绑定给这个4A房间
var john: Person?
john = Person(name: "john")
var unit4A: Apartment?
unit4A = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john
这时候 房子的实例和人的实例是互相绑定的, 如果某天 john
因为写代码加班猝死了,这时候注销john
或4A房间
的时候就会出现无法解绑的情况,执行:
john = nil
unit4A = nil
并没有调用 Person的 deinit,也没有调用Apartment的 deinit, 这就是互相强引用的问题
弱引用
使用场景: 出现以上情况怎么办,那就使用弱引用, 在房主对象前使用 weak
关键字,如下代码
class Apartment{
let unit: String
weak var tenant: Person?
init(unit: String){
self.unit = unit
}
deinit {
print("Aparment \(unit) is begin deinitialized")
}
}
使用相同的调用方式
var john: Person?
john = Person(name: "john")
var unit4A: Apartment?
unit4A = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john
剧情还是一样,john
因为某些原因挂掉了,所以要注销掉john:
john = nil
这时候可以发现触发了Person
的 deinit
:
ohn is begin deinitialized
如果jhon
还活着,直接想改他的房产证:
unit4A = nil
结果很圆满,没有执行任何 deinit
无主引用
使用场景:一个人可能不会拥有信用卡, 但是每个信用卡一定会有一个主人,无主引用与被引用对象持有相同的生命周期,需要在声明前加unowned
关键字
class Customer{
let name: String
var card: CreditCard?
init(name: String){
self.name = name
}
deinit {
print("\(name) is begin deinitialized")
}
}
class CreditCard{
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Card #\(self.number) is begin deinitialized")
}
}
以上代码描述 一个信用卡与一个持卡人关系,这里实例了一个 jane 和一张信用卡
var jane: Customer?
jane = Customer(name: "jane")
jane?.card = CreditCard(number: 1234_5678_9012_3456, customer: jane!)
信用卡与jane是绑定关系, 假设jane也因为加班猝死了,那这张卡也随之会被注销掉
jane = nil
//把jane 注销后, 触发了 jane的 deinit 和 card 的 deinit
jane is begin deinitialized
Card #1234567890123456 is begin deinitialized