使用可空性注释装饰 ObjC 代码时,您是否还必须进行定义或仅进行声明?

When decorating ObjC code with nullability annotations, do you also have to do the definition, or just the declaration?

我们正在准备一堆或 ObjC 代码供 Swift 使用,这当然需要可空性注释。现在我的理解是那些可空性注释只需要在声明位置,而不是在定义上。这意味着对于声明在 header 文件中而定义在 m/mm 文件中的情况,您不需要将它们添加到后者。

例如...

Foo.h:

- (nullable Foo *)getFooWithKey:(NSString *_Nonnull)key;

Foo.mm:

- (Foo *)subtree:(NSString *)key
{
  // Some implementation here...
}

现在我的一些对 ObjC 有更多经验的同事说他们必须在两个地方都去,这意味着 mm 文件实际上必须是这个...

Foo.mm:

- (nullable Foo *)subtree:(NSString *_Nonnull)key
{
  // Some implementation here...
}

当我问为什么时,他们说 'match' 了。但是,当我们从 m/mm 文件中删除它们时,它们似乎仍然可以在没有它们的情况下导入 Swift,因为 Swift 只查看 headers。

就是说,我不确定是否还有其他需要考虑的事情需要在我们只是没有测试的两个地方使用它们,所以我不能说这是确定的,只是我们的测试有效。

可读性与生产力

现在通常情况下,即使后者实际上没有做任何事情,如果它有助于提高可读性,那就足以说 'put it in both places'。但是,在我们的特定情况下,我们可能有 数以万计的 API 需要更新,因此消除大量额外工作对每个人来说都是一个巨大的胜利。另外,它也让写 code-mods 更容易。

我在 Apple's documentation 中找到的最接近的是这两个摘录(强调我的)...

However, in the common case there’s a much nicer way to write these annotations: within method declarations you can use the non-underscored forms nullable and nonnull immediately after an open parenthesis, as long as the type is a simple object or block pointer.

The non-underscored forms are nicer than the underscored ones, but you’d still need to apply them to every type in your header. To make that job easier and to make your headers clearer, you’ll want to use audited regions.

虽然这不是确定的。第一个可能是将其称为 'a nicer way',即 'specific to declarations',但它并没有说一般的注释只能到那里。后者也说 non-underscored 可以在 header 中使用,但同样,也没有说可空性注释通常只能出现在 header 中,只有审计区域才会出现。

就是说,有谁知道 Apple 会在哪里澄清这一点,或者可以分享任何其他信息让我们知道可以在 definitions/implementations 中跳过它们吗?

只有声明需要注释。对于方法,这意味着带有接口的头文件。