【问题标题】:What to do if [super init] returns nil?如果 [super init] 返回 nil 怎么办?
【发布时间】:2013-09-28 19:43:40
【问题描述】:

以下代码为例

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

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

更好的想法?

【问题讨论】:

  • 有点小问题 - 但你说的创建还原点是什么意思?
  • @CarlVeazey 将所有未保存的数据保存到临时文件中
  • 我会仔细考虑保存数据是否真的会帮助或伤害用户。如果您在这种情况下收到nil,显然是因为您的应用程序已经出轨了。内存中的数据很可能已经损坏。除非您可以明确地验证数据您的应用程序提供了某种版本加载方式,否则您可能会简单地销毁最后一次有效保存。
  • @bbum 好建议。

标签: objective-c


【解决方案1】:

NSObject 的 [super init] 实现永远不会返回 nil。 The base implementation just returns 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: 参数或该方法具有记录的可恢复错误时才需要执行此操作。

【讨论】:

  • 不错的答案,完全同意。
【解决方案2】:

来自文档:-

对于其他类型的错误,包括预期的运行时错误,返回 nil、NO、NULL 或其他一些适合类型的零的形式 呼叫者。这些错误的示例包括无法阅读或 写入文件,初始化对象失败,无法 建立网络连接,或未能在 收藏。如果您觉得有必要返回,请使用 NSError 对象 向发件人提供有关错误的补充信息。一个 NSError 对象封装有关错误的信息,包括错误 代码(可以特定于 Mach、POSIX 或 OSStatus 域) 和程序特定信息的字典。负值 直接返回的(nil、NO等)应该是principal 错误指示器;如果您确实传达了更具体的错误 信息,在参数中间接返回一个 NSError 对象 方法。

【讨论】:

    【解决方案3】:

    一般来说,不要在意,让nil传播。

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

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

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

    关于“制作一个还原点”,你可以尝试保存任何可能的东西,但场景如此妥协,无法保证成功。

    【讨论】:

      【解决方案4】:

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

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

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

      Apple's "Concepts in Objective C" document中,他们建议“当你创建一个对象时,你一般应该在继续之前检查返回值是否为nil:”

      【讨论】:

      • iOS 设备的内存有限。应用程序不会崩溃,但可能会出现不良行为。
      • 你应该总是在实例化一个对象后检查nil。听起来很疯狂。你检查然后呢?如果你不能实例化对象,那就放弃并接受崩溃吧,因为你真的无能为力。
      • Apple 实际上说在初始化后检查 nil,@GabrielePetronella。我已经修改了我的答案以指出该文件。
      • 他们是这么说的,但你有没有见过任何 Apple 示例代码在每次初始化后都这样做?当然不是,因为这是一种疯狂的,而且大多是无用的和过度偏执的努力。如果有你关心的特定对象,那很好,但是每次都这样做是不切实际的。
      • @GabrielePetronella - 这种做法在 Apple 示例代码中无处不在。它可能没用,也可能没用,但自从有可可以来,它一直是可可的最佳实践。
      猜你喜欢
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      相关资源
      最近更新 更多