NSKeyedUnarchiver.decodeObject
如果原始类未知,将导致崩溃/SIGABRT
。目前我所见到的唯一解决方法可以追溯到Swift早期的历史,需要使用Objective C(也是在Swift 2实现guard
,throws
,try
和catch
之前)。我可以找出Objective C的路线-但如果可能的话,我更愿意了解仅限于Swift的解决方案。
例如-数据已使用NSPropertyListFormat.XMLFormat_v1_0
进行编码。如果编码数据的类未知,则以下代码将在unarchiver.decodeObject()
处失败。
//...
let dat = NSData(contentsOfURL: url)!
let unarchiver = NSKeyedUnarchiver(forReadingWithData: dat)
//it will crash after this if the class in the xml file is not known
if let newListCollection = (unarchiver.decodeObject()) as? List {
return newListCollection
} else {
return nil
}
//...
我正在寻找一种仅适用于Swift 2的方法,在尝试使用.decodeObject
之前测试数据是否有效 - 因为.decodeObject
没有throws
- 这意味着在Swift中try-catch
似乎不是一个选项(据我所知,没有throws
的方法不能被包装)。否则,需要另一种解码数据的替代方式,如果解码失败,则会抛出错误。我希望用户能够从iCloud驱动器或Dropbox导入文件 - 因此需要进行适当的验证。我不能假设编码的数据是安全的。
NSKeyedUnarchiver
方法.unarchiveTopLevelObjectWithData
和.validateValue
都有throws
。也许可以使用这些方法之一吗?我甚至无法开始尝试在这种情况下实现validateValue
。这是否是一个可行的路线?还是我应该寻找其他方法来解决这个问题?
还是有人知道另一种解决这个问题的Swift 2的方法吗?我相信我感兴趣的密钥可能标题为$classname
- 但是说实话,我在尝试解决如何实现validateValue
方面超出了我的能力范围 - 甚至不知道这是否是坚持的正确路线。我有一种感觉自己错过了什么显而易见的东西。
编辑:这里提供一个解决方案 - 感谢下面rintaro的出色答案
最初的答案为我解决了这个问题 - 即实现委托。
但现在,我选择了基于rintaro的额外编辑响应的解决方案,如下:
//...
let dat = NSData(contentsOfURL: url)!
let unarchiver = NSKeyedUnarchiver(forReadingWithData: dat)
do {
let decodedDataObject = try unarchiver.decodeTopLevelObject()
if let newListCollection = decodedDataObject as? List {
return newListCollection
} else {
return nil
}
}
catch {
return nil
}
//...
if try unarchiver.decodeTopLevelObject() != nil
对我来说是可行的,因为我已经实现了它。如果它不是nil
,那么我就可以继续了。当我寻找抛出方法时,我错过了这个。你原来的答案对我也有用。 - simons