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

如何在Mac应用中使用@AppStorage存储SwiftUI List的选中状态

解决方案

问题根因

@AppStorage 默认仅支持 Bool、Int、Double、String、URL、Data 这类基础类型的持久化存储,无法直接识别遵从 RawRepresentable 协议的自定义枚举类型,因此你原本直接将枚举类型绑定到 @AppStorage 的写法无法正常读写存储值。

方案1:中转基础类型做转换(兼容性最高)

不需要额外扩展,直接通过中间存储字符串、自定义绑定做类型转换即可,适配所有支持 @AppStorage 的系统版本:
只需修改 ContentView 的代码如下即可:

struct ContentView: View {
    // 存储枚举的原始字符串值
    @AppStorage("selection") private var storedSelection: String = Fruit.apple.rawValue
    // 自定义绑定实现字符串和枚举的双向转换
    private var selection: Binding<Fruit> {
        Binding(
            get: { Fruit(rawValue: storedSelection) ?? .apple },
            set: { storedSelection = $0.rawValue }
        )
    }

    var body: some View {
        NavigationView {
            Sidebar(selection: selection)
            DetailView(selection: selection.wrappedValue)
        }
        .frame(width: 500, height: 300)
    }
}

方案2:扩展@AppStorage支持RawRepresentable类型(写法最简洁)

如果项目部署目标为 macOS 11+,可以扩展 @AppStorage 让它原生支持所有RawValue为@AppStorage兼容类型的枚举,添加扩展后原有代码无需修改即可正常运行:

  1. 先添加全局扩展:
extension AppStorage where Value: RawRepresentable, Value.RawValue == String {
    init(wrappedValue: Value, _ key: String, store: UserDefaults? = nil) {
        self.init(key, store: store)
        self.wrappedValue = wrappedValue
    }
}
  1. 原有代码的 @AppStorage("selection") private var selection: Fruit = .apple 可以直接正常使用。

验证说明

两种方案都可以实现选中状态的持久化,应用重启后会自动读取存储值恢复上次选中的条目,不需要额外编写状态恢复的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:24:03