5

以下面的代码为例

- (id)init {
    self = [super init];
    if (self) {
        // code
    }
    return self;
}

我不希望 nil 向上传播调用层次结构。我最初的想法是在 self 为 nil 的情况下抛出异常,创建一个还原点并中止执行。

更好的想法?

4

4 回答 4

9

NSObject 的实现[super init]永远不会返回 nil。基本实现只返回 self

通常,初始化程序返回 nil 的唯一原因是发生了非致命错误。例如,您可能调用-initWithContentsOfURL:error:并传递了无效的 URL。按照惯例,可能以这种方式失败的方法有一个error:参数,其中包含有关失败的信息。大多数初始化程序都不可能出现可恢复的错误,因此与 NSObject 一样,它们永远不会返回 nil。

致命错误通常会引发异常或中止程序。所以检查 nil 对他们没有帮助。处理致命错误的最佳选择是NSSetUncaughtExceptionHandler,尽管您应该知道在致命错误的情况下保存数据是有风险的,因为未保存的数据可能已损坏。在这种情况下不要覆盖好的数据。

为什么 Objective-c 代码总是nil在初始化器中检查,即使 super 永远不会返回 nil?公约,主要是。可以说,通过始终检查 nil,超类在将来添加失败条件变得更容易,而无需更改子类,但实际上这只是一种约定。

最后,初始化器不是检查超类初始化器失败的正确位置。如果有可能出现可恢复的错误,调用者应该检查错误。

例子:

NSError *error;
FooClass *myFoo = [[FooClass alloc] initWithContentsOfURL:blah error:&error]
if (myFoo == nil) {
  // ...
} else {
  // ...
}

初始化对象时检查 nil 是多余的。仅当存在error:参数或方法具有记录的可恢复错误时才需要执行此操作。

于 2013-09-28T22:02:11.673 回答
4

一般来说,只是不关心,让nil传播。

如果[super init]正在返回nil(即无法实例化一个新对象),那么事情就会变得非常糟糕,以至于您的应用程序很可能会在短时间内崩溃。

根据 Michael 的建议,在每次实例化后检查nil是很麻烦的,并且由于上述原因可能完全没用。

如果您担心某个特定的课程,并且您真的想尽快退出,请按照您的计划进行并抛出异常。

关于“制作还原点”,您可以尝试保存任何可能的内容,但场景如此妥协以至于无法保证成功。

于 2013-09-28T20:13:52.770 回答
4

来自文档:-

对于其他类型的错误,包括预期的运行时错误,向调用者返回 nil、NO、NULL 或其他一些适合类型的零形式。这些错误的示例包括无法读取或写入文件、无法初始化对象、无法建立网络连接或无法在集合中定位对象。如果您认为有必要将有关错误的补充信息返回给发送者,请使用 NSError 对象。NSError 对象封装了有关错误的信息,包括错误代码(可以特定于 Mach、POSIX 或 OSStatus 域)和程序特定信息的字典。直接返回的负值(nil、NO 等)应该是错误的主要指标;如果您确实传达了更具体的错误信息,

于 2013-09-28T19:46:22.807 回答
2

我想[super init]如果您尝试保留 20 gig 的内存块或其他东西(没有做 iOS 编码的人会这样做),“”可能会抛出 nil,但一般来说,nil在生产代码中很少发生“”被返回。

返回" nil" 的好处是您可以向 nil 对象发送消息并且您的应用程序不会崩溃。

但是您应该始终在实例化对象后进行检查nil,以确保您不会深入了解您的应用程序(或您的用户)无法恢复的内容。

Apple 的“Objective C 中的概念”文档中,他们建议“在创建对象时,通常应在继续之前检查返回值是否为 nil:”

于 2013-09-28T19:46:24.350 回答