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