问题
I'm unarchiving a Swift class with the following Swift code:
required convenience init(coder decoder: NSCoder) {
self.init()
horseID = decoder.decodeIntegerForKey("horseID")
name = decoder.decodeObjectForKey("name") as String!
// if the thumb key does not exist, the following line crashes
thumb = decoder.decodeObjectForKey("thumb") as UIImage!
}
The "thumb" class member was added later. I have an older archive file without the thumb data in it. Apple's documentation says that unarchiving a non-existing key returns a nil. This is the familiar Objective-C behavior. My Swift code crashes with error code: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
Changing from as
to as?
doesn't remove the problem.
This makes it difficult to extend a data model in a new version. Am I doing something wrong? I'm new to Swift.
回答1:
You're trying to force-cast it into UIImage, which will crash if decodeObjectForKey returns nil. You should replace as
with as?
to get an optional value, which you can then check if it contains a value.
If thumb isn't an optional, and you get a nil with decodeObjectForKey, you will get the error message EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
, the one you mentioned in comments. You cannot assign nil into something that is not an optional. You could fix this by giving it a default value, in case type casting would give you a nil:
thumb = decoder.decodeObjectForKey("thumb") as? UIImage ?? [default value here]
回答2:
Since you indicated the assignment to thumb
isn't executed I believe the problem is the line
name = decoder.decodeObjectForKey("name") as String!
The decoder can return nil
and you are forcing a conversion to String. If the decoder returns nil
in this case you will get an error. I recommend an implementation like this:
required convenience init(coder decoder: NSCoder) {
self.init()
horseID = decoder.decodeIntegerForKey("horseID")
name = decoder.decodeObjectForKey("name") as? String
thumb = decoder.decodeObjectForKey("thumb") as? UIImage
}
to handle nil
values that may be returned from the coder.
来源:https://stackoverflow.com/questions/28900246/swift-decodeobjectforkey-crashes-if-key-doesnt-exist