在 nil 对象上调用块给出 exc_bad_access

Calling block on a nil object gives exc_bad_access

我遇到过这种情况,当我在 nil 对象上调用块时,我的应用程序因 exec_bad_access 而崩溃。我可以通过添加 if 条件来解决问题,但我想知道为什么在 nil 对象上调用块会导致 bad_access?

@interface CustomView :UIView

@property (nonatomic, strong) UIImage* sourceImage;
@property (nonatomic, copy) void(^doneSwipingBlock)();

- (void)testMethod;

@end

//Another Class
//Sample Code (this is not the actual code but shows the crash 
CustomView view = nil;
view.sourceImage = [UIImage imageNamed:@"image.png"]; //no error as view is nil
[view testMethod]; //no error as view is nil
view.doneSwipingBlock();  //Crashes here

/*
//This works fine
if (view.doneSwipingBlock) {
    view.doneSwipingBlock();
}
*/

因为虽然块是对象,但对块的操作不应被视为尊重 Objective-C 语义。就像从 NULL 读取会导致错误访问一样,调用 NULL 块也会导致错误访问。这与函数指针的行为一致(调用 NULL 函数指针会使程序崩溃),并且由于块在 C 和 C++ 中也可用,因此使用此行为可能比纯粹的 Objective-C行为。

不通过 objc_msgSend 调用 invoke 方法,它处理和取消对 Objective-C 个对象上的 nil 对象的调用。

块是变量,不是方法。你可以从块 属性 中得到与你从 int 属性 中得到的相同的东西。它们就像你有一些名为 Block 的 class 上面有一个 invoke 方法,并且每次你需要它做一些不同的事情时,你都会对它进行 subclass 编辑, 除了编译器完成所有子 classing 部分。