Ios 块上的零检查

Ios 块上的零检查,ios,objective-c,objective-c-blocks,Ios,Objective C,Objective C Blocks,我有一个方法,它执行异步网络调用,然后通过块将成功或失败结果传回: - (void) loginWithSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError* error))failure { ... if(error) { failure(error); } else { success(responseObject); } } 我注意到,如果调用此方法并将nil作为我的块

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

- (void) loginWithSuccess:(void (^)(id responseObject))success failure:(void (^)(NSError* error))failure {
...
  if(error) {
    failure(error);
  }
  else {
    success(responseObject);
  }
}
我注意到,如果调用此方法并将
nil
作为我的块传递,我的应用程序将因
EXEC\u BAD\u访问而崩溃

[manager loginWithWithSuccess:nil failure:nil];
但是,如果我通过空块,它运行良好:

[manager loginWithWithSuccess:^(id responseObject){} failure:^(NSError *error){}];

我假设这是因为在运行时您不能将参数传递给
nil
?因此,在定义使用块的方法时,我是否应该在调用它们之前始终检查这些块是否为零?

看看Apple的框架,一些带有块参数的方法接受
NULL/nil
作为块参数(例如
animateWithDuration:animations:completion:
),其他方法则不接受(例如,
枚举对象使用块:

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

'NSInvalidArgumentException', reason: '*** -[NSArray enumerateObjectsUsingBlock:]: block cannot be nil'
那么,为什么您会获得
EXEC\u BAD\u访问权限

调用一个块时,您正在取消对地址的引用,如果地址不指向实际块,则显然无法执行此操作。中有一个很好的解释。

请尝试以下示例以了解调用块逻辑:

void (^printString)(NSString*) = ^(NSString* arg) {
    NSLog(@"%@", arg);
};

//(1) printString = ^(NSString* arg){};
//(2) printString = NULL;

printString(@"1");
在控制台中,您将看到“1”。然后取消注释(1),控制台显示“Called”,但没有错误! 最后,取消注释(2)并获取EXEC\u BAD\u访问权限。这正是您的情况


被调用的块不能为NULL或nil。在调用之前,您需要检查loginWithSuccess中是否存在传递的块。

您使用的库应该防止出现
nil
块,因为
dotthingYouDoWithCompletion:aLock error:nil
应该是您说“我不想听关于错误”的方式.@JoshCaswell谢谢,我会用nil检查。也谢谢你指出另一个答案。@RajanBalana:嗯,不。
NULL==nil
。两者都不能作为函数调用。
dispatch\u block\t crash=NULL;crash()
当然可以,@hodgesmr@JoshCaswell你是对的!这两种方法之间的重要区别当然是,在没有阻塞的情况下,该方法还能完成它的工作吗?