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


105

考虑以下方法

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

使用new nonnullnullable 注解关键字,我们可以按如下方式丰富它:

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

但我们也会收到以下警告:

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

它引用第三个参数(块一)。

文档没有提供有关如何指定块参数的可空性的示例。它说逐字记录

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

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

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

Answers:


128

这似乎正在工作

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

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

编辑:有关更多信息,请参见Swift Blog


这种NSError **类型如何工作?我似乎无法使编译器满意。
duhanebel

3
根据swift博客: 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 NSError reference. developer.apple.com/swift/blog/?
id = 25

@duhanebel答案在stackoverflow.com/questions/33198597/…中给出:(NSError * _Nullable * _Nullable)错误
Elise van Looij 2016年

33

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

NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END

在这些区域内,任何简单的指针类型都将假定为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
  • 如果错误NSError **类型,则应为NSError * _Nullable * _Nullable
  • 如果object是id *type,最好使用id _Nullable * _Nonnull,它取决于(可能是您想要的_Nullable id * _Nullabletype)。
  • 如果对象是NSObject *类型,则需要在指针后放置注解,像这样NSObject * _Nullable * _Nonnull

注意

_Nonnull并且_Nullable应在指针或id(Apple在示例代码中使用AAPLListItem * _Nullable)之后使用,但非下划线形式nonnullnullable可以在圆括号后使用。

但是,在通常情况下,有一种更好的方式来编写这些批注:在方法声明中,只要类型是简单的对象或块指针nullablenonnull就可以使用非下划线的形式并在圆括号后立即使用。

“ Nullability and Objective-C”中查看更多信息

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

  • typedef类型通常不具有固有的可为空性-根据上下文,它们可以轻松地为可为空或不可为空。因此,即使在经过审核的区域内,typedef也不假定类型为nonnull
  • 像这样的更复杂的指针类型id *必须进行显式注释。例如,要指定指向可为空的对象引用的不可为空的指针,请使用_Nullable id * _Nonnull
  • 这种特殊类型NSError **经常用于通过方法参数返回错误,因此始终假定该类型为指向可为空的NSError引用的可为空的指针。

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

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


对于弱属性,应用_Nullable。
Dongjin Suh

3

您也可以这样:

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

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



0

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

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

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


是的,但是非下划线(更细)的代码在块声明中不起作用
Paul Bruneau

-2

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

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

1
正如Apple所说,对于NSError **,您无需指定其可为空性。
DawnSong
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.