Objective c 不将NSError设置为nil会导致崩溃
我遇到了一个非常奇怪的问题,经过几个月的测试,在我准备提交应用程序的时候,这个问题碰巧出现了 我有一个folliwing方法,它获取一些JSON数据并将其转换为字典:Objective c 不将NSError设置为nil会导致崩溃,objective-c,ios,Objective C,Ios,我遇到了一个非常奇怪的问题,经过几个月的测试,在我准备提交应用程序的时候,这个问题碰巧出现了 我有一个folliwing方法,它获取一些JSON数据并将其转换为字典: NSError *e; NSMutableDictionary *result= [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:
NSError *e;
NSMutableDictionary *result= [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers error:&e];
if (e != nil) return nil;
在过去的几个月里,这种方法一直在使用,没有任何问题。但就在今天,它停止了工作。它现在总是导致错误(没有描述;只是一个非nill错误)
事实证明,我所要做的就是设置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 callapirror:e];如果(e).
能够工作,即使这实际上没有遵循NSError
API的规则,但纯粹是为了在面对错误代码时更具弹性。由于ARC将对象类型的所有自动变量置零,因此崩溃表明e
未置零,因此您不在ARC中
但是,尽管我在上面的段落中已经说过,但是您仍然不应该假设任何启用了NSError
的API在没有抛出错误时会保留NSError
值。目前实施此类API的指导方针确实说这应该是正确的,但这不是一个硬性要求。在这些准则之前编写的任何代码都可能不会以这种方式运行,在这些准则之后编写的任何代码都可能忽略它们。调用启用了NSError
的API的规则继续声明必须参考API的返回值,并且只有在返回值指示发生错误时才能遵守NSError*
变量。您的代码是错误的,您的修复也是错误的。你需要做的是说
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 callapirror:e];如果(e).
能够工作,即使这实际上没有遵循NSError
API的规则,但纯粹是为了在面对错误代码时更具弹性。由于ARC将对象类型的所有自动变量置零,因此崩溃表明e
未置零,因此您不在ARC中
然而,尽管我在上面一段中已经说过,您仍然不应该假设任何NSError
启用了API