我正在尝试捕获通过协议安全地解码未知类的NSKeyedUnarchiver
取消归档异常。NSInvalidUnarchiveOperationException
NSSecureCoding
我正在使用的解决方案基于相关的NSKeyedUnarchiverDelegate SO 帖子,通过实现委托协议NSKeyedUnarchiverDelegate
,因此我可以通过unarchiver(_:cannotDecodeObjectOfClassName:originalClasses:)
. 但是,在解码过程中遇到未知类时,似乎不会调用此委托方法。
这是我用于安全地取消归档数组对象的代码片段。
func securelyUnarchiveArrayOfCustomObject(from url: URL, for key: String) -> [MyCustomClass]? {
guard let data = try? Data(contentsOf: url) else {
os_log("Unable to locate data at given url.path: %@", log: OSLog.default, type: .error, url.path)
return nil
}
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
let delegate = UnarchiverDelegate() // Prevents `NSInvalidUnarchiveOperationException` crash
unarchiver.delegate = delegate
unarchiver.requiresSecureCoding = true // Prevents object substitution attack
let allowedClasses = [NSArray.self] // Will decode without problem if using [NSArray.self, MyCustomClass.self]
let decodedObject = unarchiver.decodeObject(of: allowedClasses, forKey: key)
let images = decodedObject as! [ImageWithCaption]?
unarchiver.finishDecoding()
return images
}
我UnarchiverDelegate
的实现就像在我指出的原始NSKeyedUnarchiverDelegate SO 帖子中一样。在我的设置下,decodeObject(of: allowedClasses, forKey: key)
不会引发异常,而是引发运行时异常:
'NSInvalidUnarchiveOperationException', reason:
'value for key 'NS.objects' was of unexpected class
'MyCustomClassProject.MyCustomClass'. Allowed classes are '{(
NSArray
)}'.'
根据其文档NSKeyedUnarchiverDelegate
,这应该只是应该调用的 那种异常:unarchiver(_:cannotDecodeObjectOfClassName:originalClasses:)
通知代理具有给定名称的类在解码期间不可用。
但在我的例子中,这个方法没有被上面的代码片段调用(即使其他委托方法,比如unarchiverWillFinish(_:)
或unarchiver(_:didDecode:)
在解码没有遇到问题时被正常调用。
与原来的帖子不同,我不能使用类函数,比如decodeTopLevelObjectForKey
我可以处理异常的地方try?
,因为我需要支持NSSecureCoding
协议的安全编码和解码,就像这里讨论的那样。这迫使我使用decodeObject(of:forKey)
,它不会抛出任何我可以处理的异常,而且,它也不会在抛出导致应用程序崩溃的运行时异常之前通知我的委托。
在什么场景下unarchiver(_:cannotDecodeObjectOfClassName:originalClasses:)
实际调用了委托方法?如何NSInvalidUnarchiveOperationException
在我的NSSecureCoding
设置下收听并做出反应,以便在解码不成功时避免运行时崩溃?