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

v1uwarro  于 2023-11-21  发布在  其他
关注(0)|答案(6)|浏览(137)

考虑以下方法

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

字符串
有了新的nonnullnullableannotation keywords,我们可以如下所示丰富它:

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


但我们也得到了这样的警告:
指针缺少空性类型说明符(__nonnull或__nullable)
它指的是第三个参数(块参数)。
documentation并没有给出如何指定块参数的空性的例子。
只要类型是简单对象或块指针,就可以在左括号后立即使用非下划线形式nullable和nonnull。
我试着把两个关键字中的一个放在块中(在任何位置),但没有任何运气。还尝试了下划线前缀变体(__nonnull__nullable)。
因此,我的问题是:如何为块参数指定空性语义?

af7jpaap

af7jpaap1#

这似乎起作用了

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

字符串
您需要为块及其参数指定为空性.
编辑:有关更多信息,请参见Swift Blog

xkrw2x1b

xkrw2x1b2#

根据Apple Blog ("Nullability and Objective-C"),您可以使用
NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END
在这些区域中,任何简单的指针类型都将被假定为nonnull

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

字符串

  • 如果errorNSError **类型,则应为NSError * _Nullable * _Nullable
  • 如果对象是id *类型,最好使用id _Nullable * _Nonnull,这取决于(可能您想要_Nullable id * _Nullable类型)。
  • 如果对象是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**中使用)

lzfw57am

lzfw57am3#

你也可以这样做:

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

字符串
这只取决于你更喜欢哪种语法。

b09cbbtk

b09cbbtk4#

为了在头文件中定义补全,我这样做了

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

字符串
当然,我同意公认的答案。

pes8fvy9

pes8fvy95#

苹果developer blog:核心:_Nullable和_Nonnull
只要类型是简单对象或块指针,就可以在左括号后立即使用非下划线形式nullable和nonnull
不带下划线的形式比带下划线的形式更好,但是你仍然需要将它们应用于标题中的每个类型

brjng4g3

brjng4g36#

以下是我在NSError**案例中使用的:

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

字符串

相关问题