【发布时间】:2015-12-10 06:28:31
【问题描述】:
这是一个关于如何优雅地规避init 在NSObject 类中的可空性的问题。
所以这是一个经典的objective-c实现:
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
static id sharedInstance;
dispatch_once(&onceToken, ^
{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
但现在我想将其声明为nonnull,如果可能的话:
+ (nonnull instancetype)sharedInstance;
不幸的是,init 返回一个 nullable instancetype 值。我应该在调用init 之后添加NSAssert 或其他内容吗?
我注意到有些人甚至document nonnull values as being in reality nullable。这有意义吗?
我是否应该大胆地在所有地方简单地添加 NS_ASSUME_NONNULL_BEGIN,而不真正确保值是 nonnull?
【问题讨论】:
-
init被定义为可为空的,因为对于无法初始化自身的对象而言,简单地返回nil而不是有效对象是合法的。NSObject不会那样做(在实践中),如果你的类直接继承自NSObject,你可以保证sharedInstance不会是nil,方法是永远不会从你的init覆盖返回nil. -
附加评论:
nullable和nonnull是定义合同的属性,而不是现实。它们让编译器知道会发生什么,因此编译器可以坚持按照合同进行正确处理。这对 Swift 来说显然很重要,它的既定目标是最大限度地减少程序员的错误。担心内存不足等情况不是您的工作,当合同另有规定时,这可能会导致引用为nil。 -
您为什么关心可空性?当然,Objective-C 中的所有变量
nullable甚至带有前缀nonnull。它是与 Swift 互操作性的发明。 Objective-C 中只有一件有用的事情:在方法中标记一些参数,它们应该有值,nil可能会导致崩溃或意外结果。 -
@Cy-4AH CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION
-
@Cy-4AH 可能想说的是,在 Objective-C 中使用
nonnull或nullable装饰方法并没有真正的优势。这是因为 Objective-C 动态调度所有消息,其中包括一个空检查。在 Objective-C 中处理空值并利用消息到 nil 模式是很常见的。仅与 Swift 互操作才有意义。因此,如果没有与 Swift 的互操作,就不要使用它。过去 30 年我们没有这样做。
标签: objective-c nullable init non-nullable objective-c-nullability