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

SwiftUI定时器中@State数组元素丢失问题排查

问题原因分析

你遇到的问题核心是代码执行顺序和异步操作的特性:

  • 按钮的action闭包是同步执行的:先给theMoveArray添加两个元素,此时print1输出2完全符合预期;紧接着创建的1秒触发定时器,其闭包不会立刻执行,而是进入异步队列等待调度;
  • 定时器创建完成后,你立刻同步执行了theMoveArray.removeAll(),直接把数组清空;
  • 1秒后定时器闭包触发时,访问的theMoveArray已经是被清空后的状态,所以print2输出0,进而触发数组越界问题。

注:这里的问题和@State的视图刷新逻辑无关,纯粹是同步代码与异步定时器的执行顺序导致的。

修复方案

如果需要定时器遍历完数组元素后再清空数组,把removeAll()移到定时器的终止逻辑里即可:

Button {
    theMoveArray.append(theMove)
    theMoveArray.append(theMove2)
    theCounter = 0
    let theArrayBounds = theMoveArray.count - 1
    print("\(theMoveArray.count)") //print1
    Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
        guard let self = self else {
            timer.invalidate()
            return
        }
        print("\(self.theMoveArray.count)")//print2
        if self.theCounter <= theArrayBounds {
            print("Timer fired! 元素内容:\(self.theMoveArray[self.theCounter])")
        } else {
            timer.invalidate()
            self.theMoveArray.removeAll() // 遍历完成后再清空数组
        }
        self.theCounter += 1
    }
} label: {
    Text("The Button")
        .frame(width: 100, height: 100)
}

额外优化建议:

  • theArrayBounds用let声明即可,无需var;
  • 定时器闭包添加[weak self]捕获,避免潜在的循环引用风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:05:10