如何在基于块的API方法中使用非空和可为空的Objective-C关键字
考虑下面的方法
- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
使用新的nonnull
和nullable
注释关键字,我们可以如下丰富它:
- (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_BEGIN
和NS_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 * _Nullable
types)。 - 如果对象是
NSObject *
types,则需要在指针之后放置注释,如下所示:NSObject * _Nullable * _Nonnull
注意
_Nonnull
和_Nullable
应该在指针或id
(苹果在示例代码AAPLListItem * _Nullable
)之后使用,但非下划线的formsnonnull
和nullable
可以在AAPLListItem * _Nullable
括号之后使用。
但是,在通常情况下,编写这些注释有更好的方法:在方法声明中,只要types是简单的对象或块指针,就可以在开放括号之后立即使用非下划线forms,可以为
nullable
或非nullable
。
检查更多的“可空性和Objective-C”
为了安全,这个规则有一些例外:
typedef
types通常不具有内在的可空性 – 根据上下文,它们可以很容易地为空或不可空。 因此,即使在审计区域内,typedef
types也不被假定为非nonnull
。- 更复杂的指针types,如
id *
必须明确注释。 例如,要指定一个可为空的对象引用的非空值指针,请使用_Nullable id * _Nonnull
。- 特定types
NSError **
经常被用来通过方法参数返回错误,它总是被假定为可为空的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;