结构体含引用类型引发内存泄漏,求非转类的解决方法
解决结构体含引用类型属性时的闭包内存泄漏问题
问题原因
结构体是值类型,当闭包捕获item时会生成一个值副本,这个副本里的aReferenceProperty会对AClass实例保持强引用。只要闭包还存在,这个结构体副本就不会被销毁,进而导致AClass实例无法被及时回收。而类作为引用类型,可以通过weak/unowned弱化捕获打破引用链,所以改成类后内存能正常释放。
可行解决方案
将结构体的引用类型属性改为弱引用(适用场景有限)
如果aReferenceProperty不需要强持有AClass实例,且AClass本身有其他强引用持有者,可以把属性改成弱引用可选类型:struct AStruct { weak var aReferenceProperty: AClass? // 其他属性... }注意:结构体中的弱引用必须是可选类型,因为弱引用的对象可能被释放变为
nil,隐式解包可选类型不适合在这里使用。用弱引用容器包装引用类型属性
如果必须保持aReferenceProperty的强引用逻辑,可以自定义一个弱引用容器类,将AClass实例包装进去:class WeakWrapper<T: AnyObject> { weak var value: T? init(value: T) { self.value = value } } struct AStruct { var aReferenceProperty: WeakWrapper<AClass>! // 其他属性... }闭包捕获结构体副本时,持有的是
WeakWrapper实例,而它对AClass是弱引用,当AClass的其他强引用全部释放后,value会自动置为nil,不会阻碍回收。只捕获需要的引用类型并弱化它
如果闭包中只需要用到aReferenceProperty,可以提前取出该引用并以weak方式捕获,避免捕获整个结构体:func someMethod(item: AStruct) { weak var weakRef = item.aReferenceProperty self.setSomeClosure { [weak self] _ in weakRef // 直接使用弱引用实例,不会强持有结构体副本 } }这种方式最直接高效,只要闭包不需要结构体的其他属性,优先考虑使用。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

