闭包中的循环引用
闭包中的循环引用原理和OC
中的block
类似。即对象A
强引用了对象B
,然后B
也强引用了A
。示例如下:
class ViewController: UIViewController {
var completionCallBack: (() -> ())?
override func viewDidLoad() {
super.viewDidLoad()
loadData {
print(self.view)
}
}
func loadData(completion: @escaping () -> ()) -> () {
completionCallBack = completion
DispatchQueue.global().async {
print("耗时操作")
Thread.sleep(forTimeInterval: 3)
DispatchQueue.main.async(execute: {
print("主线程更新UI")
//回调执行闭包
completion()
})
}
print("loadData最底部")
}
- 从
completionCallBack
属性的定义及赋值可以看出:ViewController对象
强引用了闭包completionCallBack
-
loadData
函数调用时的参数尾随闭包completionCallBack
中强引用了ViewController对象
解决方法
解除循环引用,需要打断链条。
1. OC中的方法:使用weak
使用weak
修饰变量,打破强引用,因为使用weak
修饰的变量有一次变成nil
的机会,所以需要注意解包。
weak var weakSelf = self
loadData {
print(weakSelf?.view as Any)
}
2. swift中的方法:使用[weak self]
使用[weak self]
修饰闭包原理跟OC中的__weak
类似,这样在闭包中使用self
,就是弱引用。
loadData { [weak self] in
print(self?.view as Any)
}
3. swift中的方法:使用[unowned self]
使用[unowned self]
修饰闭包,跟OC中的__unsafe_unretained
类似,不安全。
loadData { [unowned self] in
print(self.view as Any)
}
用析构函数检测是否解开了循环引用
deinit {
print("已销毁")
}
网友评论