是否可以在 init 中编写非空注释?
Posted
技术标签:
【中文标题】是否可以在 init 中编写非空注释?【英文标题】:Is it possible to write nonnull-annotation in init? 【发布时间】:2015-10-01 12:51:17 【问题描述】:现在在 Objective-c 中有两个新的注解:nonnull 和 nullable。 我应该使用它们中的哪一个来指定 init 方法的返回类型?
- (instancetype)init
if (self = [super init])
// ...
可为空的声音: 有一个“if”来检查 [super init] 返回的内容,并且不能保证它永远不会返回 nil。
非空的声音: 我不知道 init 返回 nil 的真实情况,我从不检查它。
【问题讨论】:
在某些情况下,初始化可能会失败,例如,您的对象是文件的接口,而该文件不存在或已损坏。在这种情况下,初始化可能会失败。 如果您的代码依赖于可能未指定的super
的实现,显然您不能使用nonnull
。
这取决于您继承的类及其内部逻辑。 Objectve-C 是一种非常灵活的语言。 objc 中的初始化程序与其他语言中的“构造函数”不同。初始化程序可能会因各种原因(如内部检查或其他原因)而失败。您甚至可以取消分配[super init]
给您的实例并创建另一个实例。您可能会发现阅读参考资料developer.apple.com/library/ios/documentation/General/… 很有用
@MikhailGasanov 例如[UIImage initWithData:]
说它返回“一个已初始化的 UIImage 对象,如果该方法无法从指定的数据初始化图像,则返回 nil。”
作为我的消息的补充:没有人禁止您将nonnull
放入初始化程序,但您必须注意[super init]
返回您nil
的情况。这可能涉及使用高级内存管理技术。
【参考方案1】:
对于任意类,the docs for -init
状态:
返回值:一个已初始化的对象,或 nil,如果由于某种不会导致异常的原因而无法创建对象。
随机类的init
方法可以返回nil
。如果您要从该类的子类返回 [super init]
的结果,则返回可能是 nil
。如果您的类返回可空的[super init]
的结果,则您的类应将其init
方法适当地注释为nullable
。
必须检查每个特定超类对象的init
实现,以确定子类对[super init]
的调用可以 还是不会依次返回nil
。
这表明你的方法的注解应该是nullable
,除非你确认[super init]
的结果不会是nil
。
对于NSObject
的直接子类,具体来说:
NSObject 类中定义的 init() 方法不进行初始化;它只是返回自我。在可空性方面,调用者可以假设 init() 的 NSObject 实现不返回 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
。
【讨论】:
上述来自the docs 的引用文本似乎通常指的是init
方法,而不是NSObject 的init
,特别是文档继续声明:“init
方法定义在NSObject
类没有初始化;它只是返回 self
"。所以对于NSObject
本身,这表明init
不会返回nil
。【参考方案2】:
您可以假设[[NSObject alloc] init]
永远不会失败。以下是文档的实际内容:
NSObject类中定义的init方法不做初始化;它只是返回自我。在可空性方面,调用者可以假设 init 的 NSObject 实现不返回 nil。
参考:https://developer.apple.com/reference/objectivec/nsobject/1418641-init?language=objc
【讨论】:
以上是关于是否可以在 init 中编写非空注释?的主要内容,如果未能解决你的问题,请参考以下文章