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

考虑下面的方法

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

使用新的nonnullnullable 注释关键字,我们可以如下丰富它:

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

但是我们也得到这个警告:

指针缺less可空性types说明符(__nonnull或__nullable)

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

该文档没有包含示例如何指定块参数的可空性。 它逐字叙述

只要types是一个简单的对象或块指针,就可以在打开的括号之后立即使用非下划线的forms为空或非空。

我试图把这两个关键字中的一个(在任何位置)没有任何运气。 还尝试了下划线前缀变体( __nonnull__nullable )。

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

这似乎是工作

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

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

编辑:欲了解更多信息,请参阅Swift博客

根据苹果博客(“Nullability和Objective-C”) ,你可以使用

NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END

在这些区域内,任何简单的指针types将被假定nonnull 。 那么你可以添加nullable为null的对象,这就像

 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 
  • 如果错误NSError **types,应该是NSError * _Nullable * _Nullable
  • 如果对象是id *types,最好使用id _Nullable * _Nonnull ,它取决于(可能是你想要一个_Nullable id * _Nullabletypes)。
  • 如果对象是NSObject *types,则需要在指针之后放置注释,如下所示: NSObject * _Nullable * _Nonnull

注意

_Nonnull_Nullable应该在指针或id (苹果在示例代码AAPLListItem * _Nullable )之后使用,但非下划线的formsnonnullnullable可以在AAPLListItem * _Nullable括号之后使用。

但是,在通常情况下,编写这些注释有更好的方法:在方法声明中,只要types是简单的对象或块指针,就可以在开放括号之后立即使用非下划线forms,可以为nullable或非nullable

检查更多的“可空性和Objective-C”

为了安全,这个规则有一些例外:

  • typedeftypes通常不具有内在的可空性 – 根据上下文,它们可以很容易地为空或不可空。 因此,即使在审计区域内, typedeftypes也不被假定为非nonnull
  • 更复杂的指针types,如id *必须明确注释。 例如,要指定一个可为空的对象引用的非空值指针,请使用_Nullable id * _Nonnull
  • 特定typesNSError **经常被用来通过方法参数返回错误,它总是被假定为可为空的NSError引用的可空指针。

_Nullable id * _Nonnull可以混淆, id _Nullable * _Nonnull更好理解。

_Nonnull_Nullable应该在指针或id之后使用(Apple在示例代码中使用AAPLListItem * _Nullable

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

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

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

你也可以这样做:

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

它只取决于你喜欢哪种语法。

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

只要types是一个简单的对象或块指针, 就可以在一个括号之后立即使用不带下划线的forms(可为空或不可空)。

非下划线的forms比下划线的forms更好,但是你仍然需要将它们应用到头部的每一种types

这是我用于NSError **的情况:

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