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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:10:28