我们可以确保`+(nonnull instancetype)sharedInstance;`的可空性吗? [英] Can we ensure nullability of `+ (nonnull instancetype)sharedInstance;`?

查看:170
本文介绍了我们可以确保`+(nonnull instancetype)sharedInstance;`的可空性吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个有关如何优雅地规避NSObject类中init的可空性的问题.

This is a question on how to gracefully circumvent the nullability of init in NSObject class.

这是经典的Objective-c实现:

So here is a classic objective-c implementation:

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    static id sharedInstance;
    dispatch_once(&onceToken, ^
    {
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

但是现在我想将其声明为nonnull,如果可能的话:

But now I want to declare it as nonnull, if possible:

+ (nonnull instancetype)sharedInstance;

不幸的是,init返回一个nullable instancetype值.我应该在调用init之后添加NSAssert还是其他内容?

Unfortunately, init returns a nullable instancetype value. Should I add an NSAssert or something after calling init?

我注意到有些人甚至文档nonnull值都被认为是实际上是nullable .那有道理吗?

I noticed that some people even document nonnull values as being in reality nullable. Does that make sense?

我应该大胆地在所有地方添加NS_ASSUME_NONNULL_BEGIN而不真正确保值是nonnull吗?

Should I go bold and simply add NS_ASSUME_NONNULL_BEGIN everywhere, without truly ensuring values are nonnull?

推荐答案

这里似乎有两个问题:

  1. 如何确保在我的单例sharedInstance方法中产生并由该方法返回的值在运行时实际上不为零?

  1. How do I ensure that the value produced within my singleton sharedInstance method and returned by that method is actually not nil at run time?

我如何满足我要返回nonnull指针的nullabilty注释,编译器警告和Swift桥接的系统?

How do I satisfy the system of nullabilty annotations, compiler warnings, and Swift bridging that I'm returning a nonnull pointer?

确保/执行nonnull

在某些时候,每个API合同都分解为人工合同.编译器可以帮助确保,例如,您不能获取nullable调用的结果并从返回类型为nonnull的方法中将其返回...但是通常在某个地方通常有一个原始调用,其返回类型为nonnull仅仅因为编写它的程序员说过:我保证永远不会返回null,请耐心等待,等等."

Ensuring / enforcing nonnull

At some point, every API contract breaks down to a human contract. The compiler can help ensure that, for example, you can't take the result of a nullable call and return it from a method whose return type is nonnull... but somewhere there's usually an original call whose return type is nonnull simply because the programmer who wrote it said, "I promise to never return null, cross my heart, etc."

如果您熟悉Swift,则类似于隐式解开的Optionals的情况-当您知道"一个值不能为零,但无法向编译器证明该知识时,便会使用它们在源代码外部(例如,来自情节提要或捆绑资源中的内容).

If you're familiar with Swift, this is similar to the situation with Implicitly Unwrapped Optionals — you use these when you "know" that a value cannot be nil, but can't prove that knowledge to the compiler because that knowledge is external to the source code (something from a storyboard or bundle resource, for example).

就是这种情况-您知道" init永远不会返回nil,要么是因为您为有问题的初始化程序编写了/拥有源代码,要么是因为它只是NSObjectinit,已记录为return self不做任何事情.对该初始化程序的调用将失败的唯一情况是,由于先前的alloc调用失败(因此,您正在nil上调用一个方法,该方法始终返回nil).如果alloc返回nil,则说明您已经在枯燥的海峡中,并且过程不长对于这个世界-设计API并非失败案例.

That's the situation here — you "know" that init will never return nil, either because you wrote / have source for the initializer in question or because it's just NSObject's init which is documented to return self without doing anything. The only situation where a call to that initializer will fail is because the preceding alloc call failed (and hence you're calling a method on nil, which always returns nil). If alloc is returning nil, you're already in dire straits and your process is not long for this world — this isn't a failure case to be designing API around.

(空性注释通常用于描述API的预期用途,而不是更极端的极端情况.如果API调用仅由于

(Nullability annotations are in general for describing intended use of an API, not the more extreme edge and corner cases. If an API call fails only because of a universal error it's not meaningful to annotate it as nullable; likewise, if an API fails only on input that can be ruled out via nonnull parameter annotations, the return value can be assumed nonnull.)

因此,长话短说:是的,只需将NS_ASSUME_NONNULL放在标题中,然后按原样发布sharedInstance实现即可.

So, long story short: yes, just put NS_ASSUME_NONNULL around your header, and ship your sharedInstance implementation as is.

这里不是这种情况,但是假设您有一个注释为nullable的值,但是您知道(或知道")它永远不会为零,并希望从您的nonnull注释方法中返回它. .而且您会遇到编译器警告进行尝试的情况.

It's not the case here, but suppose you have a value that's annotated as nullable, but you know (or "know") that it can never be nil and want to return it from your nonnull-annotated method. And you're in a situation where you get a compiler warning for trying.

有一种语法-只需将值转换为期望的返回类型,注释和所有内容即可:

There's a syntax for that — just cast the value to the expected return type, annotations and all:

return (NSWhatever *_Nonnull)whatever;

在您的情况下,这不是必需的-因为您正在处理idinstancetype特殊类型,所以编译器对空值转换的理解更大,并且可能一开始就不会发出警告.

In your case this shouldn't be needed — because you're dealing with the id and instancetype special types the compiler is more forgiving about nullability conversion and probably won't warn to begin with.

这篇关于我们可以确保`+(nonnull instancetype)sharedInstance;`的可空性吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆