1. weak 不是万能的
class A: NSObject {
var b: B?
deinit {
print("A died")
}
}
class B: NSObject {
var aa: A?
func setA(a: A?) {
if let a = a {
aa = a
}
}
}
var b: B! = B()
var a: A? = A()
weak var aa = a
b.setA(a: aa)
a?.b = b
a = nil // A 的 deinit 没走
b.aa = nil // A 的 deinit 走了
上面的例子说明:__strong
不是瞎用的,避免循环引用,从根源做起。 let a = a
相当于__strong
。可以短暂在一个scope{}
中强引用,不要持续持有,否则同样造成,循环引用。
2. 全局变量和单例的使用
这两个使用起来,很大的方便了代码,但一定要注意不要持有不该持有的对象,避免造成不释放。
3. weak 在闭包中的顺序很重要
class ClassA: NSObject {
var closure: (() -> ())?
}
class ClassB: NSObject {
var closure: (() -> ())?
}
class A: NSObject {
var a = ClassA()
override init() {
super.init()
a.closure = {
[weak self] in
let b = ClassB()
b.closure = {
print(self?.description ?? "??????")
}
}
}
deinit {
print("A has died!")
}
}
var a: A? = A()
a = nil // A 的 deinit 没走
class ClassA: NSObject {
var closure: (() -> ())?
}
class ClassB: NSObject {
var closure: (() -> ())?
}
class A: NSObject {
var a = ClassA()
override init() {
super.init()
a.closure = {
let b = ClassB()
b.closure = {
[weak self] in
print(self?.description ?? "??????")
}
}
}
deinit {
print("A has died!")
}
}
var a: A? = A()
a = nil // A 的 deinit 走了
上面两段代码就一句[weak self] in
位置不一样, 但第一段的造成了循环引用,虽然在 b.closure
中使用 weak
来修饰,但由于 b.closure
也在 a.closure
中,所以a.closure
优先持有 self
, 造成循环引用。第二段 b.closure
引用的是 a.closure
中的weak self
, 所以不会造成循环引用。
4. 关于 SnapKit
ConstraintMakerEditable constraint
的循环引用
var centerConstraint: ConstraintMakerEditable?
centerConstraint = make.centerX.equalTo(target)
var centerConstraint: Constraint?
centerConstraint = make.centerX.equalTo(target).constraint
ConstraintMakerFinalizable
是ConstraintMakerEditable
的父类。
通过查看 SnapKit
源码,发现make.centerX.equalTo(target)
返回的是ConstraintMakerFinalizable
, 然而 internal let description: ConstraintDescription
是 ConstraintMakerFinalizable
的一个属性,ConstraintDescription
又持有 Self
, 当Self
强持有ConstraintMakerFinalizable
时,造成循环引用,而ConstraintMakerFinalizable
的 constraint
返回的是internal let description: ConstraintDescription
的constraint
属性,Self
和internal let description: ConstraintDescription
同时持有internal let description: ConstraintDescription
的constraint
属性,不会造成循环引用。
网友评论