一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
本质是用64位的指针,把当前的side存储到64位位域中,并设置一些标记位。
Side Table 是⼀种类名为 HeapObjectSideTableEntry 的结构,⾥⾯也有 RefCounts 成员,内部是 SideTableRefCountBits,其实就是原来的 uint64_t 加上⼀个存储弱引⽤数的 uint32_t。
2.2 Unowned
和弱引⽤类似,⽆主引⽤不会牢牢保持住引⽤的实例。但是不像弱引⽤,总之,⽆主引⽤假定是永远有值。
class ZGTeacher {
var age: Int = 18
var name: String = "zhang"
}
var t: ZGTeacher?
t = ZGTeacher()
print(Unmanaged.passUnretained(t as AnyObject).toOpaque())
unowned var t1 = t
t = nil
print(t1)
这里产生了崩溃,因为unowned修饰的t1必须是假定有值的,t或者t1为nil就产生了崩溃。
当我们知道两个对象的⽣命周期并不相关,那么我们必须使⽤ weak。相反,⾮强引⽤对象拥有和强引⽤对象同样或者更⻓的⽣命周期的话,则应该使⽤ unowned。
我们来看一下这个例子:
class ZGTeacher {
var age: Int = 18
var name: String = "zhang"
var subject: ZGSubject?
}
class ZGSubject {
var subjectName: String
var subjectTeacher: ZGTeacher
init(_ subjectName: String, _ subjectTeacher: ZGTeacher) {
self.subjectName = subjectName
self.subjectTeacher = subjectTeacher
}
}
var t = ZGTeacher()
var subject = ZGSubject.init("swift", t)
t.subject = subject
这个过程中我们的Teacher和SubjectName,如果老师不在了,那么这个过程中所讲授的课程也就不在了。
这个过程中我们可以通过unowned来解决这个循环引用,也就意味着当前的生命周期ZGTeacher更长。
class ZGTeacher {
var age: Int = 18
var name: String = "zhang"
var subject: ZGSubject?
}
class ZGSubject {
var subjectName: String
///这里添加 unowned
unowned var subjectTeacher: ZGTeacher
init(_ subjectName: String, _ subjectTeacher: ZGTeacher) {
self.subjectName = subjectName
self.subjectTeacher = subjectTeacher
}
}
var t = ZGTeacher()
var subject = ZGSubject.init("swift", t)
t.subject = subject
2.3 Weak VS Unowned比较
注意weak相对于unowned更安全,但是unowned相对于weak性能更好。因为weak需要重新创建一个sideTable散列表,还要对我们当前的sideTable散列表进行操作,而unowned直接操作了我们64的信息,但是在使用过程中要确保unowned是有值的。
2.4 闭包循环引用
var age = 18
let closure = {
age += 1
}
closure()
print(age)
lldb输出打印结果
19
我们的闭包会⼀般默认捕获我们外部的变量,闭包内部对变量的修改将会改变外部原始变量的值。
下面的案例就是闭包循环引用的经典案例,对象无法释放。
class ZGTeacher {
var age: Int = 18
var name: String = "zhang"
var testClosure: (() -> ())?
deinit {
print("ZGTeacher deinit")
}
}
func test() {
let t = ZGTeacher()
t.testClosure = {
t.age += 1
}
print("end")
}
test()
那么我们如何解决这一问题哪?可以使用我们当前的捕获列表。
class ZGTeacher {
var age: Int = 18
var name: String = "zhang"
var testClosure: (() -> ())?
deinit {
print("ZGTeacher deinit")
}
}
func test() {
let t = ZGTeacher()
t.testClosure = { [weak t] in
t!.age += 1
}
print("end")
}
test()