如何在基于块的 API 方法中使用非空和可为空的 Objective-C 关键字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29647919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:33:46  来源:igfitidea点击:

How to use nonnull and nullable Objective-C keywords in block-based API method

objective-cxcodeblocknullable

提问by albertodebortoli

Consider the following method

考虑以下方法

- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;

With the new nonnulland nullableannotation keywordswe can enrich it as follows:

使用 newnonnullnullableannotation 关键字,我们可以将其丰富如下:

- (void)methodWithArg:(nonnull NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;

but we also get this warning:

但我们也收到了这个警告:

Pointer is missing a nullability type specifier (__nonnull or __nullable)

指针缺少可空性类型说明符(__nonnull 或 __nullable)

It refers to the third parameter (the block one).

它指的是第三个参数(块一)。

The documentationdoesn't cover with examples how to specify the nullability of block parameters. It states verbatim

文档不包括如何指定块参数的可为空性的示例。它逐字说明

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.

只要类型是简单对象或块指针,就可以在左括号后立即使用非下划线形式的可空和非空。

I tried putting one of the two keywords for the block (in any position) without any luck. Also tried the underscore prefixed variants (__nonnulland __nullable).

我尝试为块(在任何位置)放置两个关键字之一,但没有任何运气。还尝试了下划线前缀的变体(__nonnull__nullable)。

Therefore my question is: how can I specify the nullability semantic for block parameters?

因此我的问题是:如何为块参数指定可空性语义?

回答by Fabio Ritrovato

This seems to be working

这似乎有效

- (void)methodWithArg:(nonnull NSString *)arg1 
  andArg:(nullable NSString *)arg2 completionHandler:(nullable void (^)
  (NSArray * _Nullable results, NSError * _Nonnull error))completionHandler

You need to specify nullability both for the block and its parameters...

您需要为块及其参数指定可空性...

EDIT: For more information, see Swift Blog

编辑:有关更多信息,请参阅Swift 博客

回答by likid1412

According to Apple Blog ("Nullability and Objective-C"), you can use

根据Apple Blog ("Nullability and Objective-C"),您可以使用

NS_ASSUME_NONNULL_BEGINand NS_ASSUME_NONNULL_END.

NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END

Within these regions, any simple pointer type will be assumed to be nonnull. Then you can just add nullablefor nullable object, which like

在这些区域内,任何简单的指针类型都将被假定为nonnull. 然后你可以只nullable为可为空的对象添加,比如

NS_ASSUME_NONNULL_BEGIN

@interface MyClass: NSObject

- (void)methodWithArg:(NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;

@end

NS_ASSUME_NONNULL_END
  • if erroris NSError **type, should be NSError * _Nullable * _Nullable
  • if object is id *type, better use id _Nullable * _Nonnull, it depends (may be you want a _Nullable id * _Nullabletype).
  • if object is NSObject *type, you need put annotation after pointer, like this NSObject * _Nullable * _Nonnull
  • 如果错误NSError **类型,应该是NSError * _Nullable * _Nullable
  • 如果对象是id *类型,更好地使用id _Nullable * _Nonnull,这取决于(可能是你想要一个_Nullable id * _Nullable类型)。
  • 如果对象是NSObject *类型,则需要在指针后放置注释,如下所示NSObject * _Nullable * _Nonnull

Note

笔记

_Nonnulland _Nullableshould used after pointer or id(Apple does in the example code AAPLListItem * _Nullable), but the non-underscored forms nonnulland nullablecan used after an open parenthesis.

_Nonnull_Nullable应指针后使用或id(苹果确实在示例代码AAPLListItem * _Nullable),但是非下划线的形式nonnullnullable可在打开括号后使用。

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 nullableand nonnullimmediately after an open parenthesis, as long as the type is a simple object or block pointer.

然而,在一般情况下,有一种更好的方法来编写这些注释:在方法声明中,您可以使用非下划线形式,nullable并且nonnull紧跟在左括号之后,只要类型是一个简单的对象或块指针。

check more in "Nullability and Objective-C"

“可空性和 Objective-C”中查看更多信息

For safety, there are a few exceptions to this rule:

  • typedeftypes don't usually have an inherent nullability—they can easily be either nullable or non-nullable depending on the context. Therefore, typedeftypes are not assumed to be nonnull, even within audited regions.
  • More complex pointer types like id *must be explicitly annotated. For example, to specify a non-nullable pointer to a nullable object reference, use _Nullable id * _Nonnull.
  • The particular type NSError **is so often used to return errors via method parameters that it is always assumed to be a nullable pointer to a nullable NSErrorreference.

为了安全起见,此规则有一些例外:

  • typedef类型通常没有固有的可空性——根据上下文,它们可以很容易地为可空或不可为空。因此,即使在审计区域内,typedef也不假定类型为nonnull
  • 更复杂的指针类型,如id *必须显式注释。例如,要指定指向可空对象引用的不可为空指针,请使用_Nullable id * _Nonnull.
  • 特定类型NSError **经常用于通过方法参数返回错误,以至于它总是被假定为指向可空NSError引用的可空指针。

The _Nullable id * _Nonnullcan be confused, id _Nullable * _Nonnullis better understanding.

_Nullable id * _Nonnull可混为一谈,id _Nullable * _Nonnull是更好的理解。

_Nonnulland _Nullableshould used after pointer or id(Apple does in the example code AAPLListItem * _Nullable)

_Nonnull并且_Nullable应该在指针或之后使用id(Apple 在示例代码中这样做AAPLListItem * _Nullable

回答by OlDor

You can also do like this:

你也可以这样做:

- (id __nullable)methodWithArg:(NSString * __nullable)arg1
                        andArg:(NSString * __nonnull)arg2
             completionHandler:(void (^ __nonnull)(NSArray * __nonnull results, NSError * __nullable error))completionHandler;

It only depends which syntax you like more.

这仅取决于您更喜欢哪种语法。

回答by Krishna Kumar

To define completions in a header file I did this

为了在头文件中定义完成,我做了这个

typedef void (^PublicEventsHandler) (BOOL success, NSArray * _Nullable publicEvents);

Of course, I agree with the accepted answer.

当然,我同意接受的答案。

回答by Parag Bafna

From apple developer blog: The Core: _Nullable and _Nonnull

来自苹果开发者博客:核心:_Nullable 和 _Nonnull

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.

只要类型是简单对象或块指针,您就可以在左括号后立即使用非下划线形式可空和非空。

非下划线形式比下划线形式更好,但 您仍然需要将它们应用于 header 中的每种类型

回答by Kevin

Here is what I have used for the NSError ** case:

这是我用于 NSError ** 案例的内容:

-(BOOL) something:(int)number withError:(NSError *__autoreleasing  __nullable * __nullable)error;