Swift: decodeObjectForKey crashes if key doesn't exist

丶灬走出姿态 提交于 2019-12-13 05:53:54

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!