没有检查块

hod*_*smr 5 objective-c ios objective-c-blocks

我有一个方法执行异步网络调用,然后通过块传递成功或失败结果:

- (void) loginWithSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError* error))failure {
...
  if(error) {
    failure(error);
  }
  else {
    success(responseObject);
  }
}
Run Code Online (Sandbox Code Playgroud)

我注意到,如果我调用此方法并nil作为我的块传入,我的应用程序将崩溃EXEC_BAD_ACCESS:

[manager loginWithWithSuccess:nil failure:nil];
Run Code Online (Sandbox Code Playgroud)

但是,如果我传入空块,它运行正常:

[manager loginWithWithSuccess:^(id responseObject){} failure:^(NSError *error){}];
Run Code Online (Sandbox Code Playgroud)

我假设这是因为在运行时你不能传递参数nil?因此,在定义采用块的方法时,我应该在调用块之前检查块是否为nil?

Seb*_*ian 3

看看苹果的框架,一些带有块参数的方法接受NULL/nil块参数(例如animateWithDuration:animations:completion:),其他则不接受(例如enumerateObjectsUsingBlock:)。

如果您正在设计 API,则必须做出决定。如果没有块是有意义的,您应该nil在执行块之前接受并检查,否则您应该像这样抛出一个断言[@[] enumerateObjectsUsingBlock:nil]

'NSInvalidArgumentException', reason: '*** -[NSArray enumerateObjectsUsingBlock:]: block cannot be nil'
Run Code Online (Sandbox Code Playgroud)

那你为什么要得到EXEC_BAD_ACCESS

当调用一个块时,您会取消引用该地址,如果它不指向一个实际的块,您显然无法这样做。这个答案中有一个很好的解释。