Swift语法--12-3闭包的循环引用
闭包循环引用产生条件
- 如果在HttpTool中有对闭包进行强引用,则会形成循环引用
我们先看一段普通的代码
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
loadData { () -> () in
print("被回调了")
//在闭包中引用成员属性,需要加self
//swift中能不写self就不写self
//一般情况下只有区分参数,和在闭包中使用self
self.view.backgroundColor = UIColor.greenColor()
}
}
func loadData(finished: ()->())
{
callback = finished
// 1.加载数据
print("加载数据")
// 2.执行回调
finished()
}
当我们想把里面的闭包作为一个属性储存起来
class ViewController: UIViewController {
//设置属性用来保存闭包
//成员属性要么初始化,要么设为可选类型
//在设置闭包属性是可选类型时一定更要用一个()括住闭包的所有的类型, 否则只是指定了闭包的返回值是可选的
// 错误写法: var callback: ()->()?
var callback: (()->())?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
loadData { () -> () in
print("被回调了")
self.view.backgroundColor = UIColor.greenColor()
//闭包中强引用了self
}
}
func loadData(finished: ()->())
{
callback = finished
//viewController中的成员属性强引用了闭包
// 1.加载数据
print("加载数据")
// 2.执行回调
finished()
}
// deinit 相当于OC中的dealloc方法
// 只要一个对象释放就会调用deinit方法
deinit
{
print("88")
}
}
闭包循环引用产生原因
闭包循环引用产生原因解决方案
方案1:
- 使用weak,对当前控制器使用弱引用
- 但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包
- (该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)
// 解决方案一:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
weak var weakSelf = self //可选类型
loadData { () -> () in
print("被回调了")
//注意这里的改变
//要对weakSelf进行解包
weakSelf!.view.backgroundColor = UIColor.greenColor()
}
}
方案2:
- 和方案1类型,只是书写方式更加简单
- 可以写在闭包中,并且在闭包中用到的self都是弱引用
// 解决方案二:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
loadData {[weak self] () -> () in
print("被回调了")
//注意这里的改变
self!.view.backgroundColor = UIColor.greenColor()
}
}
方案3:
- 使用关键字unowned
- 从行为上来说 unowned 更像OC中的 unsafe_unretained
- unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
// 解决方案三:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
loadData {[unowned self] () -> () in
print("被回调了")
//注意这里的改变
self.view.backgroundColor = UIColor.greenColor()
}
}
总结
- OC中如何解决: __weak typeof(self) weakSelf = self;
- Swift中如何解决: weak var weakSelf = self
对应关系:
- __weak == weak //如果对象释放, 会自动设置为nil
- __unsafe_unretained == unowned //如果对象释放, 不会自动设置为nil,因此不是可选类型,因为一定有值
网友评论