Reputation: 5766
The decodeDouble
on NSCoder
returns a non-optional value, but I would like to identify whether a value was nil before it was encoded.
This is my scenario:
var optionalDouble: Double? = nil
func encode(with aCoder: NSCoder) {
if let optionalDouble {
aCoder.encode(optionalDouble, forKey: "myOptionalDouble")
}
}
convenience required init?(coder aDecoder: NSCoder) {
optionalDouble = aDecoder.decodeDouble(forKey: "myOptionalDouble")
// here optionalDouble is never nil anymore
}
So decoding double returns 0
in case the value was never set, so it seems like I can't identify whether a value was actually 0
or nil
before encoding
Is there a way for me to check if a double was nil before it was encoded?
Upvotes: 3
Views: 1402
Reputation: 15784
The solution is to use NSNumber instead of Double when you encode, then use decodeObject to get back (if it exists) the double value. For example
class A: NSCoding {
var optionalDouble: Double? = nil
@objc func encodeWithCoder(aCoder: NSCoder) {
if let optionalDouble = optionalDouble {
aCoder.encodeObject(NSNumber(double: optionalDouble), forKey: "myOptionalDouble")
}
}
@objc required init?(coder aDecoder: NSCoder) {
if let decodedDoubleNumber = aDecoder.decodeObjectForKey("myOptionalDouble") as? NSNumber {
self.optionalDouble = decodedDoubleNumber.doubleValue
} else {
self.optionalDouble = nil
}
}
}
With suggestion from @Hamish, here is the version for Swift 3. Be aware that we need to inherit the class to NSObject in order to make NSEncoding work (Got Unrecognized selector -replacementObjectForKeyedArchiver: crash when implementing NSCoding in Swift)
class A: NSObject, NSCoding {
var optionalDouble: Double? = nil
func encode(with aCoder: NSCoder) {
if let optionalDouble = optionalDouble {
aCoder.encode(optionalDouble, forKey: "myOptionalDouble")
}
}
override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
optionalDouble = aDecoder.decodeObject(forKey: "myOptionalDouble") as? Double
}
}
Upvotes: 6