能否在init中编写nonnull注释?

16

现在在Objective-C中有两个新的注释:nonnullnullable
我应该在init方法的返回类型说明中使用哪一个?

- (instancetype)init {
    if (self = [super init]) {
        // ...
    }
}

关于可空的参数的说明:
有一个“if”语句来检查 [super init] 的返回值,不能保证它永远不会返回 nil。

关于非空的参数的说明:
我不知道什么情况下 init 会返回 nil,也从未检查过。


有时候初始化可能会失败,比如你的对象是一个文件接口,但该文件不存在或者已经损坏。在这种情况下,初始化可能会直接失败。 - Shripada
3
如果你的代码依赖于可能未指定的super实现,显然就不能放置nonnull - Max Komarychev
3
这取决于您继承的类及其内部逻辑。Objective-C 是一种非常灵活的语言。在 Objective-C 中,初始化器与其他语言中所谓的“构造函数”不同。初始化器可能会因为内部检查或其他原因而失败。更甚者,您甚至可以释放由 [super init] 提供的实例并创建另一个实例。您可能会发现阅读参考文献 https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/Initialization/Initialization.html 很有用。 - Max Komarychev
1
例如,[UIImage initWithData:]方法返回“已初始化的UIImage对象,如果该方法无法从指定的数据初始化图像,则返回nil。”@MikhailGasanov - Max Komarychev
1
作为我的留言的补充:没有人禁止您在初始化程序中使用 nonnull,但是您必须意识到当 [super init] 返回 nil 时的情况。这可能涉及使用高级内存管理技术。 - Max Komarychev
显示剩余5条评论
2个回答

11

对于任意一个类,-init方法的文档如下:

返回值:如果无法创建对象但不会导致异常,则为已初始化的对象或nil

一个随机类的init方法可以返回nil。如果你从该类的子类返回[super init]的结果,有可能返回nil。如果init返回可空的[super init]的结果,则应适当注释其init方法为nullable

必须检查每个特定的超类对象的init实现,以确定子类调用[super init]是否可能不会反过来返回nil

这表明,除非已经确认[super init]的结果不会nil,否则你的方法声明应为nullable

对于NSObject的直接子类:

NSObject类中定义的init()方法不执行任何初始化;它只是返回self。在空值方面,调用者可以假定NSObject实现的init()不会返回nil。

因此,对于直接继承自NSObject的类,-init可以标记为nonnull

如果你的类返回nil

有可能[super init]的结果是nonnull,但你的类的init实现基于某些其他条件返回了nil

- (instancetype)init {
    if (self = [super init]) { // nonnull

        if (someFailureCondition) {
            return nil; // nullable
        }

    }

    return self;
}
在这种情况下,您的实现当然应该被注释为nullable

4
引用的文本来自文档,似乎是涉及到一般的init方法,而不是特指NSObject类的init方法。因为文档接着说明:"在NSObject类中定义的init方法不会进行任何初始化操作,它只是返回self"。所以就NSObject本身而言,这意味着init方法不会返回nil - HexAndBugs

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接