Reputation: 948
I have an array
with type [NotificationTriggers]
that I would like to store in userdefaults
. To do that, the data needs to be encoded
and decoded
. I have followed tutorials here:
https://cocoacasts.com/ud-5-how-to-store-a-custom-object-in-user-defaults-in-swift
and here:
But I still get an error that I can't seem to solve.
I have an extension
of userDefaults
where I do the magic in the get and set of the variable. NotificationTriggers
Struct
looks like this:
struct NotificationTriggers: Equatable, Codable {
var doorName: String
var notificationTrigger: String
}
Encoding
seems to work, but in decoding
I get an error
saying
Cannot convert value of type '[Any]' to expected argument type 'Data'
This is the code:
extension UserDefaults {
var notificationTrigger: [NotificationTriggers] {
get {
if let data = self.array(forKey: UserDefaultsKey.notificationTrigger.rawValue) {
do {
let decoder = JSONDecoder()
//CODE BELOW PRODUCE ERROR
if let decodedData = try decoder.decode([NotificationTriggers]?.self, from: data) {
return decodedData
}
} catch { }
}
return []
}
set {
do {
let encoder = JSONEncoder()
let data = try encoder.encode(newValue)
self.setValue(data, forKey: UserDefaultsKey.notificationTrigger.rawValue)
} catch { }
}
}
}
I have tried casting
the data:
UserDefaultsKey.notificationTrigger.rawValue) as? Data // get warning "Cast from '[Any]?' to unrelated type 'Data' always fails"
UserDefaultsKey.notificationTrigger.rawValue) as? [NotificationTriggers] // get error "Cannot convert value of type '[NotificationTriggers]' to expected argument type 'Data'"
Not sure what's missing here. Any ideas?
Upvotes: 2
Views: 357
Reputation: 26066
You save Data
for the key UserDefaultsKey.notificationTrigger.rawValue
with:
let encoder = JSONEncoder()
let data = try encoder.encode(newValue)
self.setValue(data, forKey: UserDefaultsKey.notificationTrigger.rawValue)
So the first mistake I see:
if let data = self.array(forKey: UserDefaultsKey.notificationTrigger.rawValue) {
array(forKey:)
? No, data(forKey:)
, you didn't save an Array
, you saved a Data
, a Data
that might after some decoding "hides" an Array
, but the system doesn't know it.
So, it should be:
if let data = self.data(forKey: UserDefaultsKey.notificationTrigger.rawValue) {
Then:
let decodedData = try decoder.decode([NotificationTriggers]?.self, from: data)
=>
let decodedData = try decoder.decode([NotificationTriggers].self, from: data)
Also, it's bad habit to have catch { }
, if there is an error, you might want to know it:
catch {
print("Error while doingSomethingToCustomizeHere: \(error)")
}
Upvotes: 5