SwiftUI:专门为结构属性设置userdefaults

时间:2019-11-27 09:33:42

标签: swift swiftui ios13 swift5 userdefaults

我想将映射到“ 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)
                }
            })

}
}

3 个答案:

答案 0 :(得分:0)

1。)将其保存到文件怎么办? 2.)为什么不保存喜爱的ID? (如果只是一个,我不确定)是这样的:key:“ myFavoriteID”-id

答案 1 :(得分:0)

您可以使用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) })

此帮助吗?

答案 2 :(得分:0)

这是一个示例应用程序,应该执行您想要的操作。我没有将其保存为用户默认值中的一项,而是将其保存为多个。我认为他们的关键是正确编写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