Swift:如果键不存在,则 decodeObjectForKey 崩溃

Posted

技术标签:

【中文标题】Swift:如果键不存在,则 decodeObjectForKey 崩溃【英文标题】:Swift: decodeObjectForKey crashes if key doesn't exist 【发布时间】:2015-03-06 13:52:28 【问题描述】:

我正在使用以下 Swift 代码解压缩一个 Swift 类:

 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!

后来添加了“thumb”类成员。我有一个较旧的存档文件,其中没有拇指数据。 Apple 的文档说,取消归档不存在的密钥会返回 nil。这是熟悉的 Objective-C 行为。我的 Swift 代码崩溃并出现错误代码:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)。

as 更改为as? 并不能解决问题。

这使得在新版本中扩展数据模型变得困难。难道我做错了什么?我是 Swift 新手。

【问题讨论】:

as UIImage! 是强制转换,如果返回值为 nil 会崩溃。您是否尝试过可选演员 as? UIImage thumb = decoder.decodeObjectForKey("thumb") as? UIImage 也会崩溃 您是否设置了调试停止并检查了thumb 的内容? 未执行对 thumb 的分配。在此之前代码崩溃。 @ThomasZimmer 这似乎很棘手,您能在某处提供源代码并在此处分享链接吗? 【参考方案1】:

您试图将其强制转换为 UIImage,如果 decodeObjectForKey 返回 nil,它将崩溃。您应该将as 替换为as? 以获得可选值,然后您可以检查它是否包含值。

如果 thumb 不是可选的,并且您使用 decodeObjectForKey 得到 nil,您将收到错误消息 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0),即您在 cmets 中提到的错误消息。您不能将 nil 分配给非可选内容。你可以通过给它一个默认值来解决这个问题,以防类型转换会给你一个 nil:

thumb   = decoder.decodeObjectForKey("thumb") as? UIImage ?? [default value here]

【讨论】:

我在 Martin R 的评论之后尝试过,但结果是一样的 - 崩溃。 @ThomasZimmer 它是否因相同的错误消息而在同一行崩溃?您能在此处提供完整的错误消息吗? EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) 是确切的错误 你有没有尝试在分配名称时更改为as??因为如果将 thumb nil 分配给它,它确实不应该崩溃,除非 thumb 不是可选的。 alkku,“拇指”是可选的。正如你提到的那样改变线路并没有改变奇怪的崩溃。【参考方案2】:

由于您表示未执行对thumb 的分配,我相信问题出在这条线

name    = decoder.decodeObjectForKey("name") as String!

解码器可以返回nil,并且您正在强制转换为字符串。如果解码器在这种情况下返回nil,您将收到错误消息。我推荐这样的实现:

required convenience init(coder decoder: NSCoder) 
    self.init()

    horseID = decoder.decodeIntegerForKey("horseID")
    name    = decoder.decodeObjectForKey("name") as? String
    thumb   = decoder.decodeObjectForKey("thumb") as? UIImage

处理可能从编码器返回的nil 值。

【讨论】:

sbooth,不,第一行(“名称”从解码器中出来)被正确执行。所以问题在于从解码器分配“拇指”值的行。更改“作为 UIImage!”进入“as?UIImage”再次导致崩溃。 即便如此,如果由于某种原因decoder 不包含name 的值,我相信强制转换也会发生类似的崩溃。

以上是关于Swift:如果键不存在,则 decodeObjectForKey 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如果键不存在则发送 null

如果字典键不可用,则返回 None

ConcurrentDictionary操作

如果存在数组,则需要 Laravel 验证数组元素

检查 JSON 数组中是不是存在值,如果不存在则检查下一个数组(Swift / SwiftUI)

如果不存在,则追加对象 swift