Cœu*_*œur 6 nullable objective-c init non-nullable objective-c-nullability
这是一个如何优雅地规避课堂上的可空性的init问题NSObject.
所以这是一个经典的objective-c实现:
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
static id sharedInstance;
dispatch_once(&onceToken, ^
{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)
但是现在我想声明它nonnull,如果可能的话:
+ (nonnull instancetype)sharedInstance;
Run Code Online (Sandbox Code Playgroud)
不幸的是,init返回一个nullable instancetype值.我应该NSAssert在打电话后添加一个什么东西init?
我注意到有些人甚至将价值观记录nonnull在现实中nullable.那有意义吗?
我应该大胆地简单地添加到NS_ASSUME_NONNULL_BEGIN任何地方,而不是真正确保价值观nonnull吗?
这里似乎有两个问题:
如何确保在我的单例sharedInstance方法中生成并由该方法返回的值在运行时实际上不是零?
我如何满足nullabilty注释,编译器警告和Swift桥接系统,我正在返回一个nonnull指针?
nonnull在某些时候,每个API合同都会分解为人工合同.编译器可以帮助确保,例如,您不能接受nullable调用的结果并从返回类型为nonnull... 的方法返回它,但某处通常是原始调用,其返回类型nonnull仅仅是因为编写的程序员它说,"我保证永远不会归零,交叉我的心等等"
如果您熟悉Swift,这与Implicitly Unwrapped Optionals的情况类似 - 当您"知道"某个值不能为零时使用这些,但无法向编译器证明该知识,因为该知识是外部的源代码(例如来自故事板或包资源的东西).
那这里的情况-你"知道" init将永远不会返回零,或者是因为你写/有源有问题的初始化或因为它只是NSObject的init被记录到return self没有做任何事情.调用该初始化程序失败的唯一情况是因为前面的alloc调用失败(因此您正在调用一个nil始终返回的方法nil).如果alloc返回nil,你已经陷入了困境,你的过程对于这个世界来说并不长 - 这不是设计API的失败案例.
(可空性注释通常用于描述API的预期用途,而不是更极端的边缘和极端情况.如果API调用仅因为通用错误而失败,则将其注释为可空是没有意义的;同样,如果API仅失败在可以通过非空参数注释排除的输入上,可以假设返回值是非空的.)
所以,长话短说:是的,只需把NS_ASSUME_NONNULL你的标题放在一边,sharedInstance按原样运送你的实现.
nonnull可空这不是这里的情况,但假设你有一个注释为的值nullable,但你知道(或"知道")它永远不会是零并想要从你nonnull注释的方法中返回它.而且你遇到了编译器警告的情况.
有一个语法 - 只需将值转换为预期的返回类型,注释和所有:
return (NSWhatever *_Nonnull)whatever;
Run Code Online (Sandbox Code Playgroud)
在你的情况下,这应该没有必要-因为你处理的id和instancetype特殊类型的编译器是更宽容有关的为空的转换,可能会不发出警告的开始.
| 归档时间: |
|
| 查看次数: |
1623 次 |
| 最近记录: |