SwiftUI中用Timer Publisher更新LazyVStack内项的UI无响应问题
解决SwiftUI LazyVStack列表项定时不更新的问题
问题根源
你的listItemModels是被@Published修饰的数组,而MyListItemModel是值类型(struct)。当你直接修改数组内元素的timeInMs属性时,数组本身的内存内容并未发生整体变更,@Published无法检测到这种局部修改,因此不会向SwiftUI发送UI更新通知,导致LazyVStack内的列表项无变化。
修复方案
核心思路是通过生成新的数组或新的元素实例,触发@Published的更新通知,具体修改如下:
修改ViewModel的
updateModelsTimeLeft方法
将直接修改数组元素属性的逻辑,改为生成新的MyListItemModel实例并替换整个数组:private extension MyViewModel { func updateModelsTimeLeft() { // 遍历原数组,生成每个元素的更新版本,组成新数组 listItemModels = listItemModels.map { model in var updatedModel = model // 这里替换成你的时间更新逻辑,示例为每秒减1000ms updatedModel.timeInMs = max(0, model.timeInMs - 1000) return updatedModel } } }这种方式会给
listItemModels赋值一个全新的数组,@Published会立即检测到变化并通知SwiftUI刷新UI。确认ListItemView的接收逻辑
确保ListItemView正确接收并展示timeInMs,示例实现:struct ListItemView: View { let model: MyListItemModel var body: some View { Text("剩余时间: \(model.timeInMs)ms") } }由于每次更新都会生成新的
MyListItemModel实例,ForEach会自动识别对应id的元素变化,触发ListItemView的刷新。
额外验证点
- 你的Timer配置是正确的:
on: .main确保回调在主线程执行,符合SwiftUI的UI更新要求。 fetchData方法在@MainActor修饰的ViewModel中,async调用后更新listItemModels的逻辑是线程安全的,无需额外处理。
内容的提问来源于stack exchange,提问作者Whirlwind
相关产品推荐
相关产品推荐

