SwiftUI List删除条目内存泄漏问题求助(iOS15及以上可复现)
SwiftUI List/Lazy容器删除条目内存泄漏问题解决办法
问题确认
你遇到的问题确实存在:在iOS15、iOS16系统中,使用SwiftUI的List、LazyVStack或LazyVGrid删除条目后,作为数据源的Item类实例无法被释放(deinit方法不触发),根源是懒加载容器的内部缓存机制持有了对旧数据的强引用。
可行解决办法
办法1:修改数组赋值方式触发完全刷新
原代码中仅修改数组内容但未改变数组引用,SwiftUI可能不会完全清理旧视图的引用。可以通过重新生成数组实例触发视图完全刷新:
.onDelete { indexes in data.remove(atOffsets: indexes) // 重新赋值数组,强制视图刷新并释放旧实例 data = data }
或者直接用filter生成全新数组:
.onDelete { indexes in let targetIndexes = IndexSet(indexes) data = data.enumerated().filter { !targetIndexes.contains($0.offset) }.map { $0.element } }
办法2:将Item改为值类型(Struct)
如果业务场景允许,把Item从class改为struct。值类型的内存管理更契合SwiftUI的设计逻辑,不会出现此类强引用滞留问题:
struct Item: Identifiable { let id: String init(id: String) { self.id = id } }
(注:值类型无需deinit方法,会随作用域自动释放)
办法3:显式控制视图标识
在ForEach中明确指定id参数,并给List设置动态标识,数据变化时强制整个列表刷新:
List { ForEach(data, id: \.id) { item in Text(item.id) } .onDelete { indexes in data.remove(atOffsets: indexes) } } .id(data.map { $0.id }) // 用所有条目id的组合作为列表标识,数据变更时触发完全刷新
补充说明
该问题在iOS17及后续版本中已被Apple官方修复,升级系统版本也可直接解决此问题。
内容的提问来源于stack exchange,提问作者josip04
相关产品推荐
相关产品推荐

