objective-c - 不将 NSError 设置为 nil 会导致崩溃

标签 objective-c ios

我遇到了一个非常奇怪的问题,经过几个月的测试后,我正要提交应用程序时恰好弹出。

我有以下方法,它接受一些 JSON 数据并将其转换为字典:

NSError *e;
NSMutableDictionary *result= [NSJSONSerialization JSONObjectWithData:jsonData 
                              options:NSJSONReadingMutableContainers error:&e];
if (e != nil) return nil;

这几个月一直在不停地使用这个方法,完全没有问题。但就在今天,它刚刚停止工作。它现在总是导致错误(没有描述;只是一个非空错误)。

事实证明,我必须做的就是设置 NSError *e = nil; 来解决这个问题。我认为这样做只是一种很好的做法,并不是绝对重要的。这让我害怕。我想知道我在我的代码中还有多少次这样做。谁能解释可能发生的事情?

此外,我正在使用 ARC,我想这让发生这种情况变得更加奇怪。

最佳答案

您的代码有误,您的修复也有误。你需要做的就是说

if (result == nil) {
    // an error occurred, and the NSError* variable can now be consulted
}

如果result除了nil还有什么, 那么你就不能对 e 的内容进行任何假设.


这里的基本原因是具有 NSError** 的 API除非 API 返回错误,否则不需要返回值来将任何内容放入该位置。通常这意味着在非错误情况下,它们根本不会修改值,所以无论您在 e 中有什么之前的变量就是你之后的变量。如果你的代码是在没有 ARC 的情况下编译的,你的 e变量将包含堆栈中的垃圾。在 ARC 下它将被初始化为 nil ,但我猜你不在 ARC 之下,原因我会讲到。

然而,它比这更复杂。即使该方法没有返回错误,它仍然可能修改了 NSError**。反正值。简单的例子是如果这个方法调用另一个方法,传递相同的 NSError**进入该方法,然后从错误中恢复并返回成功值。然而,第二种方法可能已经填充了你的 NSError*带有不再有效的错误的变量。

现在,我认为您的代码不是 ARC 的原因是,据我所知,现在所有的 Cocoa API 都在努力修改 NSError**值,除非发生错误。这符合一两年前制定的新指南(是在 2011 年初还是 2012 年初,我忘了是哪一个)说具有 NSError** 的方法。参数应该只在错误情况下修改它。这旨在允许显示 NSError *e = nil; [foo callAPIWithError:e]; if (e) ... 的代码工作,即使这实际上并没有遵循 NSError 的规则API,纯粹作为一个实际问题,在面对不正确的代码时更具弹性。由于 ARC 消除了所有具有对象类型的自动变量,因此您的崩溃表明 e没有消失,因此你不在 ARC 中。

然而,尽管我在上一段中刚刚说过,你仍然不应该假设任何 NSError -enabled API 将保留 NSError没有错误抛出时单独的值。当前实现此类 API 的指导方针确实说这应该是正确的,但这并不是硬性要求。在这些准则之前编写的任何代码可能不会那样做,而在这些准则之后编写的任何代码可能只是忽略它们。调用 NSError 的规则-enabled API 继续声明必须查询 API 的返回值,并且 NSError*仅当返回值指示发生错误时才可观察到变量。

关于objective-c - 不将 NSError 设置为 nil 会导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13847207/

相关文章:

objective-c - 如何检查 NSString 的最后一个字符

objective-c - subview 方向错误

ios - 可以在拒绝选项选择后以编程方式调用 iOS 推送通知警报吗?

iOS UITests NSLocalizedString 不工作

ios - Storyboard UIScrollView 将无法正常工作

ios - SKSpritenode:物理质量不会因重力而改变加速度

ios - swift:将 alamofire 中的 JSON 数据解析为带有数组的字典

ios - 有没有办法在Apple Watch中输入文字

iphone - 我已经注册了 App ID,但它仍然显示您没有适用于 iOS 应用程序的合格 Bundle ID。在这里注册一个

iphone - Obj-C "@interface"的类文件?