【问题标题】:SwiftUI: setting userdefaults specifically to struct propertiesSwiftUI:专门为结构属性设置用户默认值
【发布时间】:2020-03-22 19:46:28
【问题描述】:

我想将映射到“id”的变量“isfavorite”设置为 UserDefaults。我能够将编码为 JSON 的整个结构保存到 UserDefaults。然后在初始化时解码 UserDefaults JSON。 这种方法有两个问题

1) 我正在使用 UserDefault 存储一个 JSON 文件,该文件可能会随着时间的推移而变得更大,这不是 UserDefaults 的理想用例

2) 我无法在初始化期间更新内容,UserDefaults 上最后保存的 JSON 正在加载

struct Labvalueslist: Codable, Identifiable, Equatable {
    var topic: String
    var sirange: String
    var usrange: String
    var id: Int
    var isfavorite: Bool }

var labvaluesdata: [Labvalueslist] = load("labvalues.json")

final class UserData: ObservableObject {
    @Published var labvaluesUserdata = labvaluesdata
        {
        didSet {
            let encoder = JSONEncoder()
            if let encoded = try?
                encoder.encode(labvaluesUserdata) {
                UserDefaults.standard.set(encoded, forKey: "isfavorite")
            }
        }
    }
    init () {
        if let labvaluesUserdata = UserDefaults.standard.data(forKey: "labvaluesUserdata")
        {
            let decoder = JSONDecoder()
            if let decoded = try?
                decoder.decode([Labvalueslist].self, from: labvaluesUserdata) {
                self.labvaluesUserdata = decoded
                return
            }
        }
        self.labvaluesUserdata = labvaluesdata
    }
}

struct ImageView: View {
    var list: Labvalueslist

    @ObservedObject var userData = UserData()

    var anatomyfavIndex: Int {
        userData.labvaluesUserdata.firstIndex(where: { $0.id == list.id})!
    }
// This is where I am confused; how do I get the "isfavorite" mapped to "id" and store it as UserDefaults and use only those values on init 

var body: some View {

            VStack {
        ScrollView {
            VStack(alignment: .leading)
            {
            Text("Normal Range:").font(.headline)
            HStack
                { Text("SI: " + list.sirange)
                Spacer()
                Text("US: " + list.usrange)
                }
            .padding(EdgeInsets(top: 10, leading: 0, bottom: 10, trailing: 0))
            }
        }.foregroundColor(.black)
            }.navigationBarTitle(Text(list.topic), displayMode: .inline)
           .padding(EdgeInsets(top: 10, leading: 10, bottom: 0, trailing: 5))
                .navigationBarItems(trailing: Button(action: {
                    self.userData.labvaluesUserdata[self.anatomyfavIndex].isfavorite.toggle()
                }) {
                    if self.userData.labvaluesUserdata[self.anatomyfavIndex].isfavorite {
                        Image(systemName: "star.fill").foregroundColor(.yellow).scaleEffect(1.5).padding (.trailing, 20)
                    }
                    else {
                        Image(systemName: "star")
                            .foregroundColor(.yellow)
                            .scaleEffect(1.5)
                            .padding (.trailing, 20)
                }
            })

}
}

【问题讨论】:

    标签: swift swiftui ios13 swift5 userdefaults


    【解决方案1】:

    1.) 将其保存到文件中怎么样? 2.) 你为什么不保存最喜欢的 id? (如果只是一个,我不确定)像这样: key: "myFavoriteID" - id

    【讨论】:

    • "favorite" 可以是多个。这就是为什么我为 id 表示的每个主题使用切换 self.userData.labvaluesUserdata[self.anatomyfavIndex].isfavorite.toggle()
    • 好的,那你为什么不保存一组你最喜欢的 id 呢?
    • 是的。好主意啊。会尝试。你能指导我如何创建它。 P.S:我不是软件背景。医生正在尝试编码。
    • 以: favoriteIDs : [Int] = [] 开头。 -> stackoverflow.com/questions/37599632/… 。在该链接中,您可以看到如何将该数组保存/读取到文件中。
    • 如何在 isfavorite 切换打开时拉出“anatomyfavIndex” id?
    【解决方案2】:

    您可以使用 map 从结构数组中获取 [Bool] 数组。

    @State var isfavoriteArray : [Bool] = labvaluesdata.map{$0.isfavorite}
    

    如果你想将 isfavorite 绑定到 id - 你可以像这样获取字典数组 [id: isfavorite]

    @State var idIsFaveDict: [Int: Bool] = Dictionary(uniqueKeysWithValues: labvaluesdata.map { ($0.id, $0.isfavorite) })
    

    这有帮助吗?

    【讨论】:

    • 不。我将如何将其存储为 UserDefaults 并将其加载到 init...
    • UserDefaults.standard.set(isfavoriteArray, forKey: "isfavoriteArray") 你是什么意思在初始化时加载它?您已经在 init 上加载了 userdefaults。你的意思是你想在应用程序启动时获取数组?在这种情况下,将 .onAppear{isfavoriteArray = Userrdefaults.Standart...} 添加到 ScrollView。
    • 当前 init 的问题是它正在加载整个 JSON 文件;这使得无法更新任何内容。每次都会加载 userdefault 中的 JSON。
    • 您是否考虑过将其从 init 中删除并执行一次 .onAppear{} ? .每次发生更改时保存更改,但仅在 .onAppear{} 中加载。
    • 我能够做到你提到的事情。但是当我尝试保存 UserDefaults“尝试插入非属性列表对象”时出现此错误
    【解决方案3】:

    这是一个示例应用程序,它应该可以满足您的需求。我没有将其保存为用户默认值中的一个条目,而是将其保存为多个。我认为他们的关键是正确编写 ObservableObject。

    struct ContentView: View {
        var body: some View {
            VStack {
                ButtonView(key: "favorite:1")
                ButtonView(key: "favorite:ab12")
                ButtonView(key: "favorite:2jjf")
            }
        }
    }
    
    struct ButtonView: View {
        @ObservedObject private var userDefaultsKey: UserDefaultsKey
    
        init(key: String) {
            userDefaultsKey = UserDefaultsKey(key: key)
        }
    
        var body: some View {
            Button(action: buttonTapped) {
                Text(userDefaultsKey.key + ": " + (userDefaultsKey.value ? "liked" : "not liked"))
            }
        }
    
        func buttonTapped() {
            UserDefaults.standard.set(!userDefaultsKey.value, forKey: userDefaultsKey.key)
        }
    }
    
    class UserDefaultsKey: ObservableObject {
        let key: String
    
        @Published var value = false
    
        init(key: String) {
            self.key = key
    
            value = UserDefaults.standard.bool(forKey: key)
    
            NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: nil) { [weak self] _ in
                guard let self = self else { return }
                self.value = UserDefaults.standard.bool(forKey: self.key)
            }
        }
    }
    

    请注意,在模拟器中,除非您在模拟器中实际退出应用程序,否则不一定会保存用户默认值(如果您从 Xcode 再次运行,有时不会保存用户默认值:Xcode 9 simulator doesn't save userdefaults

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多