You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体含引用类型引发内存泄漏,求非转类的解决方法

解决结构体含引用类型属性时的闭包内存泄漏问题

问题原因

结构体是值类型,当闭包捕获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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:38:27