您的代码是错误的,您的修复也是如此。你需要做的是说
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
启用了 - 的 APINSError
在没有抛出错误的情况下都会单独保留该值。当前实现此类 API 的指南确实说这应该是正确的,但这不是硬性要求。在这些指南之前编写的任何代码可能不会以这种方式运行,并且在指南之后编写的任何代码都可能会忽略它们。调用NSError
启用的 API 的规则继续规定必须查阅 API 的返回值,并且NSError*
只有在返回值指示发生错误时才能观察变量。