如何在基于块的 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
How to use nonnull and nullable Objective-C keywords in block-based API method
提问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:
使用 newnonnull和nullableannotation 关键字,我们可以将其丰富如下:
- (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_BEGIN和NS_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 beNSError * _Nullable * _Nullable - if object is
id *type, better useid _Nullable * _Nonnull, it depends (may be you want a_Nullable id * _Nullabletype). - if object is
NSObject *type, you need put annotation after pointer, like thisNSObject * _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),但是非下划线的形式nonnull和nullable可在打开括号后使用。
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
nullableandnonnullimmediately 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 benonnull, 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 nullableNSErrorreference.
为了安全起见,此规则有一些例外:
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;

