我遇到了一个非常奇怪的问题,经过几个月的测试后,我正准备提交应用程序。
我有一个folliwing方法,它接受一些JSON数据并将其转换为字典:
NSError *e;
NSMutableDictionary *result= [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers error:&e];
if (e != nil) return nil;
在过去的几个月里,这种方法已经停止使用,绝对没有问题。但就在今天,它刚刚停止工作。它现在总是导致错误(没有描述;只是一个非nill错误)。
事实证明,解决问题所需要做的就是设置NSError *e = nil;
。我认为做这件事只是一种好习惯,而不是绝对批评。这吓到我了。我想知道我在代码中做了多少次。任何人都可以解释可能发生的事情吗?
另外,我正在使用ARC,我想这会发生这种情况更加奇怪。
答案 0 :(得分:4)
您的代码错误,您的修复也是如此。你需要做的是说
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都在努力而不是修改{{ 1}}值,除非发生错误。这符合一年或两年前建立的新指南(可能是在2011年或2012年初,我忘记了哪些),说具有NSError**
参数的方法只应在错误中修改它案件。这是为了允许代码NSError**
工作,即使它实际上没有遵循NSError *e = nil; [foo callAPIWithError:e]; if (e) ...
API的规则,纯粹作为一个实际问题,在面对错误时更具弹性码。由于ARC使用对象类型清除所有自动变量,因此崩溃表明NSError
未被填空,因此您不在ARC中。
然而,尽管我刚刚在上一段中说过,但您仍然不应该假设任何启用了e
的API都会在没有引发错误时单独保留NSError
值。目前实施此类API的准则确实应该是真的,但这并不是一项艰难的要求。在这些指南之前编写的任何代码都可能不会那样,并且在指南之后编写的任何代码都可能忽略它们。调用启用了NSError
的API的规则继续声明必须查询API的返回值,并且只有在返回值指示发生错误时才可以观察到NSError
变量。
答案 1 :(得分:2)
让我逐步解释错误的原因:
NSError *e; //some garbage non-nil value may be here
NSMutableDictionary *result= [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers error:&e]; // no error, e is untouched, garbage is still here
if (e != nil) return nil; // there was no error but because of garbage we think there was one
首先,您需要检查结果值或将e变量设置为nil(首选的是首选)。
答案 2 :(得分:0)