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

Swift结构体中使用@AppStorage实现独立按钮状态持久化遇阻

解决多按钮独立禁用状态持久化问题

问题核心

@AppStorage的键必须是编译时常量,无法用实例属性(比如你的level)作为动态键,所以直接在ButtonData里写@AppStorage(level)会报错。下面提供两种可行的解决思路:


方案1:手动操作UserDefaults

放弃@AppStorage包装器,直接通过UserDefaults读写状态,这样就能用level作为动态键:

struct ButtonData {
    let id = UUID()
    let level: String
    let bgColor: String
    let image: String
    
    // 读取/写入禁用状态
    var isDisabled: Bool {
        get { UserDefaults.standard.bool(forKey: level) }
        set { UserDefaults.standard.set(newValue, forKey: level) }
    }
}

使用时直接修改isDisabled即可,UserDefaults会自动完成持久化,重启APP后状态依然保留。


方案2:用ObservableObject统一管理状态

如果按钮数量较多或需要更复杂的状态操作,可以用ObservableObject封装所有按钮的禁用状态,同样基于UserDefaults实现持久化:

class ButtonStateManager: ObservableObject {
    // 从UserDefaults加载初始状态,修改时自动同步到本地
    @Published private var disabledStates: [String: Bool] {
        didSet {
            UserDefaults.standard.set(disabledStates, forKey: "buttonDisabledStates")
        }
    }
    
    init() {
        self.disabledStates = UserDefaults.standard.dictionary(forKey: "buttonDisabledStates") as? [String: Bool] ?? [:]
    }
    
    // 获取指定level的禁用状态
    func isDisabled(for level: String) -> Bool {
        disabledStates[level] ?? false
    }
    
    // 设置指定level的禁用状态
    func setDisabled(_ disabled: Bool, for level: String) {
        disabledStates[level] = disabled
        objectWillChange.send()
    }
}

// 简化ButtonData,状态交由Manager管理
struct ButtonData {
    let id = UUID()
    let level: String
    let bgColor: String
    let image: String
}

在View中使用时,需要注入状态管理器:

struct ContentView: View {
    @StateObject private var stateManager = ButtonStateManager()
    let buttons: [ButtonData] = [
        ButtonData(level: "level1", bgColor: "red", image: "star"),
        ButtonData(level: "level2", bgColor: "blue", image: "moon")
    ]
    
    var body: some View {
        VStack {
            ForEach(buttons) { button in
                Button(action: {
                    stateManager.setDisabled(true, for: button.level)
                }) {
                    Image(systemName: button.image)
                        .padding()
                        .background(Color(button.bgColor))
                }
                .disabled(stateManager.isDisabled(for: button.level))
            }
        }
    }
}

这个方案的优势是状态集中管理,方便后续扩展(比如批量重置状态、监听全局状态变化等)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:37:17