Reputation: 157
My app saves settings to a file on an iOS device by archiving instances of a class with properties. The class uses the NSCoding protocol, and therefore, I encode these properties using encodeWithCoder. I then try to read these files back into memory using a command such as tempInt = decoder.decodeIntegerForKey("profileFlags") as Int
This has worked well so far, but now I need to be able to store additional properties and retrieve them. In essence, the structure of this archived object is being changed, but users will already have files with the old structure (which has fewer properties). If the user has a file with the new structure (additional properties), then I want to read them. If not, I want to be able to execute code to handle that and provide default values.
I tried using a nonexistent key tempInt = decoder.decodeIntegerForKey("nonExistentKey") as Int
, expecting to get a nil value, but it returned a zero. Unfortunately, this is one place where I really need an optional, because 0 is a valid value.
The closest help article I can find is Swift: decodeObjectForKey crashes if key doesn't exist but that doesn't seem to apply here. It seems like decodeObjectForKey returns an optional and decodeIntegerForKey returns an Integer.
Any ideas on how to do this?
Upvotes: 7
Views: 1071
Reputation: 236568
You can use decodeObjectForKey
that returns nil instead of zero. You just need to downcast to Int as follow:
decoder.decodeObjectForKey("profileFlags") as? Int
Upvotes: 2
Reputation: 131511
@luk2302 gave you the answer, but I wanted to adjust the syntax slightly and expand on it:
var tempInt: Int?
let key = "profileFlags"
let hasValue = decoder.containsValueForKey(key)
tempInt = hasValue ? decoder.decodeIntegerForKey(key) : nil
The last statement is using the "tertiary operator", which has the same effect as:
if hasValue
{
tempInt = decoder.decodeIntegerForKey(key)
}
else
{
tempInt = nil
}
...but all in 1 line. It's a little odd-looking until you get used to it, but it is a very concise way to express this sort of thing.
Upvotes: 0
Reputation: 57204
You can check using decoder.containsValueForKey("nonExistentKey")
wether or not there is an actual value present and only if it is extract it with decodeIntegerForKey
:
if decoder.containsValueForKey("nonExistentKey") {
let tempInt = decoder.decodeIntegerForKey("nonExistentKey")
}
Upvotes: 11