以下面的代码为例
- (id)init {
self = [super init];
if (self) {
// code
}
return self;
}
我不希望nil传播调用层次结构。我最初的想法是抛出一个异常,以防self为零,建立一个恢复点并中止执行。
更好的想法?
答案 0 :(得分:9)
NSObject的[super init]
实现永远不会返回nil。 The base implementation just returns self
通常,初始化程序返回nil的唯一原因是发生了非致命错误。例如,您可能已调用-initWithContentsOfURL:error:
并传递了无效的网址。按照惯例,可能以这种方式失败的方法具有error:
参数,其中包含有关失败的信息。大多数初始化程序都没有可恢复错误的可能性,因此像NSObject一样,它们永远不会返回nil。
致命错误通常会抛出异常或中止程序。因此检查nil对他们没有帮助。处理致命错误的最佳选择是NSSetUncaughtExceptionHandler,尽管您应该知道在发生致命错误的情况下保存数据存在风险,因为未保存的数据可能已损坏。在这种情况下,不要覆盖好的数据。
为什么objective-c代码总是在初始值设定项中检查nil
,即使super永远不会返回nil?公约,主要是。可以说,通过始终检查nil,超类在将来添加失败条件变得更容易,而不需要更改子类,但实际上它只是一个约定。
最后,initalizer不是检查超类初始化程序失败的正确位置。如果可能出现可恢复的错误,则调用者应检查错误。
示例:
NSError *error;
FooClass *myFoo = [[FooClass alloc] initWithContentsOfURL:blah error:&error]
if (myFoo == nil) {
// ...
} else {
// ...
}
初始化对象时检查nil是否过度。只有在存在error:
参数时才需要执行此操作,或者该方法具有记录的可恢复错误。
答案 1 :(得分:4)
来自文档: -
对于其他类型的错误,包括预期的运行时错误,返回 nil,NO,NULL或其他类型 - 适合的零形式 呼叫者。这些错误的例子包括无法阅读或 写一个文件,初始化一个对象失败,无法做到 建立网络连接,或无法找到对象 采集。如果您觉得有必要返回,请使用NSError对象 有关错误的补充信息给发件人。一个NSError object封装有关错误的信息,包括错误 代码(可以特定于Mach,POSIX或OSStatus域) 以及程序特定信息的字典。负值 直接返回(nil,NO等)应该是主体 错误指标;如果你确实传达了更具体的错误 信息,间接返回一个NSError对象的参数 方法
答案 2 :(得分:4)
一般来说,只是不在乎让nil
传播。
如果[super init]
正在返回nil
(即无法实例化新对象),那么某些内容会非常糟糕,以至于您的应用程序可能会在短时间内崩溃。
按照迈克尔的建议,在每次实例化后检查nil
都很麻烦,而且由于上述原因可能完全没用。
如果您担心某个特定课程,并且您真的想尽快拯救,请按照您的计划继续进行并抛出异常。
关于“制作还原点”,您可以尝试保存任何可能的内容,但这种情况会受到影响,因此无法保证成功。
答案 3 :(得分:2)
我认为“[super init]
”如果你试图保留一个20 gig的内存块或其他东西(没有人会做iOS编码的话)就可以抛出nil,但总的来说,“{{1} “返回很少发生在生产代码中。
返回“nil
”的好处是你可以向nil对象发送消息,你的应用程序不会崩溃。
但在实例化对象后,您应该始终对nil
进行检查,以确保您不会太深入了解您的应用(或您的用户)无法恢复的内容。
在Apple's "Concepts in Objective C" document中,他们建议“当您创建对象时,通常应该在继续之前检查返回的值是否为nil:”。