在Swift中对于引用类型的对象采用的就是自动内存管理,即系统会帮我们处理好内存的申请和分配。当初始化创建对象的时候系统自动分配内存,而在释放内存的时候会遵循自动引用计数原则,但需要注的是Swift中的ARC只针对引用类型对象,且还不得不提醒大家注意一下循环引用中一些常见的坑及其解决办法,一起来看看吧。 更加详细的可以参照这篇博客写的 (http://www.jianshu.com/p/bf2b8f278a81)
1.闭包引起的循环引用
// 声明一个闭包
var completionBlock: (([String]) -> ())?
func loadData(completion: @escaping ([String]) -> ()) -> () {
let arr = ["1", "2"]
// 使用属性记录了闭包 -> self 对闭包引用
completionBlock = completion
completion(arr)
}
// 在这个方法内,闭包对self进行了引用,所以会产生循环引用
loadData { (array) in
print(self.view)
}
2.闭包引起的循环引用的解决方法:
- 按照OC的解决方法
/**
1.细节 var week 只能修饰var 不能修饰 let
// weak let weakself = self 这种写法是错误的
2.'weak' must be a mutable variable, because it may change at runtime
3.weak可能在运行时被修改 -> 指向的对象一旦被释放,会被自动设置为nil
*/
weak var weakSelf = self
loadData2 { (array) in
// 解包有两种方式的解包,这个在使用的时候需要注意
// ? 可选解包,如果self 已经被释放,就不会向对象发送 getter方法,更加安全
print(weakSelf?.view ?? ())
// ! 强制解包,如果self 已经被释放,强行解包会导致崩溃,
print(weakSelf!.view)
// weakSelf?.view - 只是单纯的发送消息,没有参与计算
// 强行解包,因为需要参与计算,可选项不能直接参与到计算
}
- 采用Swift的方法,推荐方法
// [weak self] 表示{}中所有的self都是弱引用,需要注意解包操作
loadData2 { [weak self] (arrar) in
print(self?.view ?? ())
}
- Swift的另外一种方法,不推荐
// [unowned self] 表示{}中所有的self都是assin类型的,不会强引用,但是如果对象释放,指针地址不会变化,
// 如果对象释放,继续调用,就会出现野指针的错误,这一点和weak是不一样的。
// 这个关键字的作用有点类似于OC中 __unsafe_unretained
loadData2 { [unowned self] (arrar) in
print(self.view ?? ())
}
未完待续……
网友评论