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

SwiftUI视图未同步User Defaults更新状态问题求助

问题解决方法

1. 改造AppSecurityStore为可观察对象

让单例类遵循ObservableObject,同时添加应用前台激活监听,确保后台切回时视图能同步最新值:

import SwiftUI

final class AppSecurityStore: ObservableObject {
    static let shared = AppSecurityStore()
    
    private init() {
        // 监听应用回到前台事件,触发视图更新
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(refreshValue),
            name: UIApplication.willEnterForegroundNotification,
            object: nil
        )
    }
    
    @Published var isAppLockEnabled: Bool {
        get {
            UserDefaults.standard.bool(forKey: "AppLock")
        }
        set {
            UserDefaults.standard.setValue(newValue, forKey: "AppLock")
        }
    }
    
    @objc private func refreshValue() {
        // 手动发送变更通知,强制视图读取最新值
        objectWillChange.send()
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

2. 修正ContentView的状态持有方式

将@State替换为@StateObject(iOS14+),因为AppSecurityStore是引用类型,需要用ObservableObject对应的属性包装器:

struct ContentView: View {
    @StateObject private var appSecurityStore: AppSecurityStore
    
    init(appSecurityStore: AppSecurityStore = .shared) {
        self._appSecurityStore = StateObject(wrappedValue: appSecurityStore)
    }
    
    var body: some View {
        Form {
            Section {
                Toggle("App Lock", isOn: $appSecurityStore.isAppLockEnabled)
            }
        }
    }
}

核心逻辑说明

  • ObservableObject + @Published:让SwiftUI能追踪属性变化,修改值时自动刷新视图
  • 前台激活监听:应用从后台返回时,手动触发变更通知,确保视图同步UserDefaults中的最新值
  • @StateObject:稳定持有ObservableObject实例,适配视图生命周期,避免重复创建或丢失状态

可选优化:监听UserDefaults实时变化

如果需要监听其他组件修改同一UserDefaults Key的情况,可在AppSecurityStore的init中添加:

UserDefaults.standard.addObserver(
    self,
    forKeyPath: "AppLock",
    options: [.new],
    context: nil
)

然后实现监听方法:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "AppLock" {
        objectWillChange.send()
    }
}

并在deinit中移除该观察者:

UserDefaults.standard.removeObserver(self, forKeyPath: "AppLock")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:23:13