循环引用,即 A 强引用 B,B 强引用 A,对象销毁时会出现,A、B都无法销毁,因为A、B在相互等对方销毁,可是谁也没有办法先销毁
一、采用弱引用 避免循环引用
引用有3种情况:
1、默认强引用,即不做任何修饰
2、弱引用 [weak self],在对象被被释放后会将 self =nil,与 OC weak修饰一样效果
3、无宿主引用 [unowned self],对象释放后,不会设置为 nil,非安全调用会导致闪退,与 OC assign 修饰类似
class Util : NSObject {
var block : (()->())?
static let shared : Util = {
let o = Util()
return o
}()
func doSomething(callback: @escaping()->Void) {
block = callback
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 5, execute: {
print("callback ()->()")
(self.block ?? {print("completion==nil")})()
})
}
}
class LoginViewController: UIViewController {
var domain: LoginDomain!
deinit {
print("\(self) 释放")
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
print(self.domain.title)
// 弱引用,不会导致循环引用问题
/*
1、Util.shared 是单例,进程存在则不会被销毁
2、doSomething 回调用 会被 Util.shared 单例【强引用持有】
3、doSomething 回调中如果再强引用 self 时,就会导致相互 controller与Util.shared 相互持有对方,从而导致无法释放
*/
// Util.shared.doSomething {
// print("do()->Void " + self.domain.title)
// }
/*
4、如果 doSomething 回调使用 弱引用,则 callback 不会强制持有 self(controller),及时 callback 被util.shared持有不释放,依然不会影响 controller 的 deinit
5、弱引用可以使用 guard 简洁写法,然而 该写法可能会导致业务执行不完整的请求,guard let self = self else {return} 如果controller被释放了,callback 就直接 return了,后续业务无法执行
*/
Util.shared.doSomething {[weak self] in
// 通俗写法 guard let self = self else {return}
guard let self = self else {
print("self 已经释放")
return
}
print("do()->Void guard " + self.domain.title)
}
/*
6、不使用 guard,写法不那么优雅,需要 ?或 ??逐个判别对象
*/
// Util.shared.doSomething { [weak self]in
// if self == nil {
// print("self 已经释放")
// }
// print("do()->Void " + (self?.domain.title ?? "") )
// }
}
}
网友评论