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

Swift Pomodoro应用@AppStorage跨视图更新异常求助

解决@AppStorage同步问题及计时器旧值复用问题

问题1:修改任务后主视图计时器沿用旧值

核心原因是计时器依赖的本地变量未监听@AppStorage属性的变化,或启动计时器时未读取最新存储值。

解决步骤:

  • 在主视图中,为每个taskXTimeLeft添加onChange监听,当对应任务时间被修改时,若当前选中该任务,立即更新计时器的当前时间:
    .onChange(of: task1TimeLeft) { newValue in
        if taskSelected == 1 {
            currentTime = newValue
        }
    }
    
  • 切换任务(taskSelected变化)时,从@AppStorage重新读取对应任务的时间,赋值给计时器的当前时间变量,若计时器正在运行则重启:
    .onChange(of: taskSelected) { newValue in
        switch newValue {
        case 1: currentTime = task1TimeLeft
        case 2: currentTime = task2TimeLeft
        case 3: currentTime = task3TimeLeft
        case 4: currentTime = task4TimeLeft
        default: currentTime = 0
        }
        
        if isTimerRunning {
            timer?.upstream.connect().cancel()
            startTimer()
        }
    }
    
  • 计时器运行时,将currentTime的变化同步回对应的@AppStorage属性,保证跨视图数据一致:
    private func startTimer() {
        timer = Timer.publish(every: 1, on: .main, in: .common)
        _ = timer?.sink { _ in
            guard currentTime > 0 else {
                toggleTimer()
                return
            }
            currentTime -= 1
            
            switch taskSelected {
            case 1: task1TimeLeft = currentTime
            case 2: task2TimeLeft = currentTime
            case 3: task3TimeLeft = currentTime
            case 4: task4TimeLeft = currentTime
            default: break
            }
        }
    }
    

问题2:taskSelected设为0后无法修改

关键是确保所有视图通过同一个@AppStorage键访问taskSelected,且修改操作直接作用于@AppStorage属性。

解决步骤:

  • 检查所有涉及taskSelected的视图,统一使用@AppStorage("taskSelected") var taskSelected: Int = 0声明,避免混用@State或错误键名。
  • 所有修改taskSelected的操作直接修改该属性,不要调用UserDefaults.standard.set(@AppStorage会自动处理同步):
    // 正确写法
    Button("选择任务1") {
        taskSelected = 1
    }
    
    // 错误写法,会导致同步异常
    // Button("选择任务1") {
    //     UserDefaults.standard.set(1, forKey: "taskSelected")
    // }
    
  • 排查视图中是否有条件逻辑阻止taskSelected修改,比如按钮是否在taskSelected == 0时被禁用,或存在其他判断限制。

额外注意事项

  • 无需调用已废弃的UserDefaults.standard.actualize(),@AppStorage在iOS 15+(Xcode 13对应版本)会自动监听UserDefaults变化并更新视图。
  • 确保所有@AppStorage属性的类型一致(比如taskSelected统一为Int,不要在某个视图中写成可选值)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:06:28