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

SwiftUI使用List搭配id: \.self出现内存泄漏部分对象未销毁如何解决

问题根因

这是macOS Monterey Beta 5到早期正式版中SwiftUI的已知底层bug:当List使用引用类型的Hashable对象本身(id: \.self)作为唯一标识时,List内部的单元格复用缓存会强持有部分已删除的元素对象,不会主动释放,从而出现内存泄漏。


可行解决方案

方案1:新增List唯一标识强制刷新(侵入性最低,完全保留原有功能)

不需要修改任何业务逻辑、TestObj实现和多选逻辑,只需要给List添加.id()修饰符,绑定到数组的元素数量,触发数组变更时List完全重建清空缓存:

List(model.objs, id: \.self) { obj in
    Text(obj.text)
}
.id(model.objs.count) // 新增这一行

该方案原理是:当数组元素数量变化时,SwiftUI会判定为这是一个全新的List,销毁原有List实例和所有内部缓存资源,原本被缓存强持有的对象就会正常释放,同时完全保留Set<TestObj>类型的多选功能。

方案2:提升系统最低支持版本

该bug已经在macOS 12.3及以上的正式版中被苹果官方修复,如果你的应用可以将最低部署版本提升到macOS 12.3或更高版本,不需要修改任何代码即可解决该问题。

方案3:手动管理对象引用

如果必须兼容macOS 12.2及更低版本,也不想用方案1的刷新逻辑,可以每次删除元素后手动生成全新的数组副本赋值给objs,切断对原有对象的引用:

// 删除时的逻辑修改为生成新数组,而非原地修改
Button(action: {
    model.objs = model.objs.enumerated()
        .filter { $0.offset % 2 != 0 }
        .map { $0.element }
}) {
    Text("Remove half")
}

内容的提问来源于stack exchange,提问作者recaptcha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 17:27:04