NSKeyedUnarchiver unarchiveObjectWithData 返回 nil

Posted

技术标签:

【中文标题】NSKeyedUnarchiver unarchiveObjectWithData 返回 nil【英文标题】:NSKeyedUnarchiver unarchiveObjectWithData returning nil 【发布时间】:2016-01-01 21:37:35 【问题描述】:

我有一个类使用NSCoder/NSKeyedArchiverNSKeyedUnarchiver 进行序列化和反序列化。我有单元测试,旨在检查我对序列化格式中各种错误的处理(这不是简单的存档,而是包含存档)。

但是,自从我升级到 Swift 2/ios 9 后,测试显示了一些不寻常的行为。以前,无效存档的测试失败,因为反序列化无效存档会引发 Objective-C 异常,正如文档所述,由于 Swift 无法捕获它们而导致程序崩溃。这很好,我打算在将来的某个时候修复测试。

现在,测试通过了。当喂给我的随机或确定性垃圾时,我会从unarchiveObjectWithData 收到nil,而不是异常。我已经检查了此方法的文档,并且没有列出任何行为更改。

坦率地说,我发现这种行为变化非常可疑,因为没有任何地方提到这种变化是如何发生的或为什么发生的。我之前失败的单元测试现在刚刚通过,没有明显的原因。

这是新的预期行为(它返回nil)吗?如果没有,我如何才能获得实际的预期行为(Obj-C 异常)而不是 nil 无效存档?

【问题讨论】:

【参考方案1】:

Swift2/iOS9 在NSKeyedUnarchiver 中引入了undocumented throws 类方法:

extension NSKeyedUnarchiver 
    @warn_unused_result
    public class func unarchiveTopLevelObjectWithData(data: NSData) throws -> AnyObject?

但如果数据格式完全错误,它似乎不起作用:它返回nil而没有错误。

let dat = "test".dataUsingEncoding(NSUTF8StringEncoding)!
try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(dat) // -> `nil`

只有当解压器在解码时发现一些无效的实体(例如未知的类名)时才会抛出错误。我认为这是一种错误,或者是由于实现不完整而意外发布的。

无论如何,如果你想要Objective-C异常,你可以构造NSKeyedUnarchiver

let dat = "test".dataUsingEncoding(NSUTF8StringEncoding)!
let unarchiver = NSKeyedUnarchiver(forReadingWithData: dat) // -> throws Objective-C exception

但是,还没有 throws 初始化器...?

【讨论】:

谢谢。我想我现在将构建 NSKeyedArchiver 并手动处理该 ObjC 异常,这样我就不会处于这个奇怪的未记录的半实现步骤中。

以上是关于NSKeyedUnarchiver unarchiveObjectWithData 返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

NSKeyedUnarchiver.unarchiveObject 不工作 [重复]

NSKeyedUnarchiver.unarchiveObject() 取消归档旧对象

NSKeyedUnarchiver - 删除解码的数据?

NSKeyedUnarchiver - 需要尝试/捕获?

如何将代表与 NSKeyedUnarchiver 一起使用?

NSKeyedUnarchiver.unarchivedObject 为字典返回 nil