首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSKeyedUnarchiver -需要尝试/捕捉吗?

NSKeyedUnarchiver -需要尝试/捕捉吗?
EN

Stack Overflow用户
提问于 2013-06-25 14:01:53
回答 2查看 5.5K关注 0票数 21

据我所知,不鼓励使用@try/@catch块,因为只有在无法恢复的灾难性错误时才会抛出exceptions (请参阅本讨论,并给出@bbumiOS中的异常处理的一个很好的答案)。

因此,我查看了我的代码,发现了一个不知道如何处理的@try/@catch块:

代码语言:javascript
复制
NSData *fileData = [NSData dataWithContentsOfFile: ....];

NSDictionary *dictionary;

@try {
   dictionary = [NSKeyedUnarchiver unarchiveObjectWithData: fileData];
}
@catch (NSException *exception) {
   //....
}
@finally {
  //...
}

问题是(如文档中所述),如果NSData不包含有效存档,则NSData将引发NSInvalidArchiveOperationException

由于数据是由用户选择的文件提供的,因此不能保证它包含有效的存档,因此如果选择了不正确的文件,应用程序就会崩溃。

现在有两个问题:

  1. 如果存档无效,为什么+unarchiveObjectWithData:不返回nil (编辑:NSError**) (这似乎不符合灾难性或不可恢复的错误)。
  2. 上面的模式正确吗(使用@try)?我没有找到让我们预先检查数据是否包含有效存档的方法,也没有发现使用委托协议处理这种情况的可能性。我忽略了安提兴?

请注意,上面的代码当然有效,我只是想知道这是否是最佳实践。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-25 15:19:21

NSKeyedArchiver是由苹果制造的。它们控制在unarchiveObjectWithData:执行时执行的代码,因此它们还控制异常处理期间的资源管理(这是Objective中异常背后的麻烦来源)。

如果他们能够保证在您调用unarchiveObjectWithData:和代码中引发异常的点之间没有外部代码(无论是第三方代码还是应用程序代码),理论上就可以安全地使用异常,只要调用代码能够正确地清理。

问题是,这种假设可能不是这样的:使用NSKeyedArchiver来序列化自定义对象是很常见的。通常,自定义类实现initWithCoder:来读取类数据(通过使用归档程序的方法(如decodeObjectForKey:) )。

如果归档程序在这些方法中抛出异常,则无法修复归档程序的资源处理。异常将通过自定义对象的initWithCoder:抛出。归档程序不知道是否有比反序列化对象更多的东西需要清理。因此,在这种情况下,异常的出现意味着进程处于危险状态,可能会导致不必要的行为。

关于你的问题:

为什么NSKeyedArchiver不使用适当的Cocoa错误处理?

只有建立档案的苹果工程师才知道。我的猜测是,异常处理和键控归档是在大致相同的时间(2001年左右)构建的,当时还不清楚异常处理永远不会成为目标C中的头等公民。

@try模式正确吗?

由于上述注意事项的局限性,它是正确的。如果Apple的代码正确地处理异常情况,而您自己的序列化代码也是这样,那么@try模式可能是正确的。

然而,要实现完全正确是非常困难的。您必须确保所有已执行的代码都知道异常并正确地进行清理。

例如,默认情况下,为局部变量和临时对象设置没有例外的清理 (您必须使-fobjc-arc-exceptions能够这样做)。

此外,没有关于@合成属性访问器的异常安全性的文档(当atomic可能泄漏一个锁时)。

结论:

有无数种微妙的方法可以解释异常如何打破某些东西。在Objective中构建异常安全代码是困难的,并且需要深入了解所有相关部分的实现情况。

所有这些都得出了结论。如果您希望在加载可能损坏的档案时优雅地处理错误,然后继续正常执行:不使用

票数 10
EN

Stack Overflow用户

发布于 2015-10-27 23:11:38

iOS 9中添加到NSKeyedUnarchiver中的一个新方法现在返回一个错误:

斯威夫特

代码语言:javascript
复制
public class func unarchiveTopLevelObjectWithData(data: NSData) throws -> AnyObject?

目标-C:

代码语言:javascript
复制
+ (nullable id)unarchiveTopLevelObjectWithData:(NSData *)data error:(NSError **)error;

但是,这与以前版本的iOS并不是向后兼容的,因此您需要使用检查框架可用性

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17299396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档