Swift 内存管理与循环引用问题(weak、unowned)
来源:互联网 发布:sql定义变量${} 编辑:程序博客网 时间:2024/04/28 02:38
之前我在CSDN上写过一篇博客:OC内存管理、ARC、property属性、__strong、__weak(),大家有兴趣的可以去看看。
今天我们来整理一下Swift的内存管理与循环引用的解决问题-weak、unowned:
内存管理
swift的内存管理也是使用的ARC(自动引用技术):当我们初始化创建一个对象实例的时候,swift就会替我们管理和分配内存,此时的引用计数为1,当对其进行init(copy/mutableCopy)时,引用计数会+1,而当实例被销毁时,引用计数就会-1。当系统检测到引用计数为0的时候,就会释放掉这个内存。
但是,这种引用计数会产生一个问题就是循环引用:
循环引用
class A { var b:B? init() { print("A初始化") } deinit { print("A析构掉") }}class B { var a:A? init() { print("B初始化") } deinit { print("B析构掉") }}var a:A?; a = A()var b:B?; b = B()a!.b = b; b!.a = aa = nil; b = nil
你会发现,A和B的析构函数deinit都没有调用,因为当a执行析构的时候,b.a还在对其进行引用,当b析构的时候,a.b也在对b进行引用。这时候解决的方法就是对其中的某一个声明进行若引用,即加上weak:
weak var b:B?
另外一种造成循环引用的问题就是闭包:闭包中对任何元素的引用都会被闭包自动持有,如果我们在闭包中需要使用self的话,那就相当于闭包对self持有,而block又是被self直接或间接持有,这样就造成了循环引用。例如下面的代码:
class C{ var name:String lazy var block:()->() = { print(self.name ) } init(name:String) { self.name = name print("C初始化") } deinit { print("C析构") }}var c:C? = C(name:"c")c?.block()c = nil
这里C的析构函数也是没有执行的。block是self的属性,block里面又对self持有,这就形成了循环引用。所以这里我们可以使用unowned,也可以使用weak:
//unowned
lazy var block:()->() = {[unowned self] in print(self.name)}//weaklazy var block:()->() = {[weak self] in if let strongSelf = self{ print(strongSelf.name) }}
那么这两个使用有什么区别呢?接下来看一个例子:
class C{ var name:String lazy var block:()->() = {[unowned self] in print(self.name) } init(name:String) { self.name = name print("C初始化") } deinit { print("C析构") }}class D{ var block:(()->())! init(callBack:(()->())?) { self.block = callBack! print("D构造") } deinit { print("D析构") }}var c:C? = C(name:"c")var d = D.init(callBack:c?.block)c!.block()c = nild.block()
这里当你运行到 d.block()的时候,是会有一个error。
因为当d.block()执行的时候,c已经被析构掉了,而闭包里的self肯定也是不存在的,是一个nil,这个时候执行的话self.name就会报错。所以在我们不确定是否有外部变量在持有这个block的时候,我们就应该使用weak更为安全,因为使用weak的话self.name需要改成可选性的self?.name,这个时候self?.name肯定就为nil了。所以换成weak之后,在playground里的d.block()就不会有错误了,而且block也是会正常执行的,只不过print(self?.name)打印出来为nil。
欢迎大家访问我的github:https://github.com/FCF5646448,如果有能帮助到大家的地方,可以鼓励我个小星星哦
- Swift 内存管理与循环引用问题(weak、unowned)
- Swift 内存管理,WEAK 和 UNOWNED
- Swift里的内存管理:内存管理、weak和unowned
- Swift开发必备技巧:内存管理、weak和unowned
- Swift开发必备技巧:内存管理、weak和unowned
- 内存管理,WEAK 和 UNOWNED
- 内存管理,WEAK 和 UNOWNED
- iOS 内存管理(unowned,weak)
- Swift-weak & unowned
- Swift 引用计数总结 Strong,Weak, unowned 简单使用
- 14.7 Swift中unowned解决循环强引用
- Swift: Memory Management -> Weak, Unowned, Strong
- Swift unowned和weak的区别
- swift ARC中的strong、weak、unowned
- swift ARC中的strong、weak、unowned
- 14.5 Swift中unowned引用
- Swift的循环引用以weak
- Swift内存管理(ARC)之循环引用
- skyline 剖面分析MeasureTerrainProfile
- Spring MVC 静态文件处理
- 常见数据结构整理总结
- Android Studio2.2 配置NDK
- JS微信公众号支付开发
- Swift 内存管理与循环引用问题(weak、unowned)
- 解决 eclipse移植androidstudio 找不到静态库的问题
- 【Spring】 Bean的注入
- [转载]Java使用Jedis操作Redis并发时遇到的坑记录
- Java实现简单的RPC框架
- linux IDE开发工具
- 【算法题】赛马
- android PullToRefreshListView onRefreshComplete 无效问题
- jmeter不同线程组之间传递参数(参数是加密的)(转)