I have the following property wrapper to store my values:
@propertyWrapper struct UserDefault<T: Codable> {
var key: String
var wrappedValue: T? {
get {
if let data = UserDefaults.standard.object(forKey: key) as? Data {
return try? JSONDecoder().decode(T.self, from: data)
}
return nil
}
set {
if let encoded = try? JSONEncoder().encode(newValue) {
UserDefaults.standard.set(encoded, forKey: key)
}
}
}
}
I store my values in the following Class:
class AppState: ObservableObject {
@UserDefault(key: "achievements") var achievements: [String : Bool]?
}
In my Struct I try to read values, but I always get nil. What am I missing?
struct XXX {
AppState().achievements = [:]
AppState().achievements?["Normal"] = true
print("ACHIEVEMENTS")
print(AppState().achievements)
}
With a ? I get nil, when I try to unwrap this value the app crashes. What do I need to do to write and read from my achievement variable?
Aside from the structural issues (you appear to be putting bare expressions in the body of a struct
, when these should be in a func
), the issue comes down to not referring to the same instance of AppState
when creating the achievements
initially.
Everytime you call AppState()
, you're creating a new instance.
func testWithProblem() {
// Creating an instance of AppState and setting achievements...
AppState().achievements = [:]
// Creating another instance! The first instance is now gone from memory.
// achievements on this instance is nil, so the next line has no effect.
AppState().achievements?["Normal"] = true
print("ACHIEVEMENTS")
// Yet another instance...
print(AppState().achievements)
}
You make sure you're referring to the same instance.
func testItWorksNow() {
// You need to use the same instance...
let appState = AppState()
appState.achievements = [:]
// So this line will refer to the same achievements dict as you've just created.
appState.achievements?["Normal"] = true
print("ACHIEVEMENTS")
print(appState.achievements)
}