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

SwiftUI中用Timer Publisher更新LazyVStack内项的UI无响应问题

解决SwiftUI LazyVStack列表项定时不更新的问题

问题根源

你的listItemModels是被@Published修饰的数组,而MyListItemModel是值类型(struct)。当你直接修改数组内元素的timeInMs属性时,数组本身的内存内容并未发生整体变更,@Published无法检测到这种局部修改,因此不会向SwiftUI发送UI更新通知,导致LazyVStack内的列表项无变化。

修复方案

核心思路是通过生成新的数组或新的元素实例,触发@Published的更新通知,具体修改如下:

  1. 修改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。

  2. 确认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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 06:55:02