我遇到了这个场景,当我在一个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();
}
*/
答案 0 :(得分:6)
因为虽然块是对象,但块上的操作不应被视为遵循Objective-C语义。就像从NULL读取导致访问不良一样,调用NULL块会导致访问不良。这与函数指针的行为一致(调用NULL函数指针会使程序崩溃),并且由于块在C和C ++中也可用,因此使用此行为比纯粹的Objective-C行为更有意义。
不通过objc_msgSend
调用invoke方法,int
处理和取消对Objective-C对象上的nil对象的调用。
块是变量,而不是方法。您可以从块属性中获得与Block
属性相同的内容。他们就像你有一个名为invoke
的类,它上面有一个{{1}}方法,每次你需要它做一些不同的事情时你都会将它子类化,除了编译器完成所有的操作子类化部分。