2015-01-07 2 views
-1

Я столкнулся с этим сценарием, когда мое приложение разбилось с помощью exec_bad_access, когда я вызываю блок на объекте nil. Я смог исправить проблему, добавив условие if, но я хочу знать, почему вызывающий блок на объекте nil вызывает bad_access?Вызывающий блок на объекте nil дает exc_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

Отсутствует '*' в декларации 'CustomView view'. Вы уверены, что код, который сбой, скопирован в это сообщение дословно? –

+0

@IanMacDonald: он говорит: «// Пример кода (это не настоящий код, но показывает крах», так что это явно не так. – zneak

ответ

6

Поскольку блоки являются объектами, операции над блоками не следует воспринимать как относящиеся к семантике Objective-C. Точно так же, как чтение из NULL вызывает плохой доступ, вызов блока NULL вызывает плохой доступ. Это согласуется с поведением указателя функции (вызов указателя функции NULL приводит к сбою вашей программы), и поскольку блоки доступны также на C и C++, возможно, было более разумно использовать это поведение, чем чисто поведение Objective-C ,

Метод вызова не вызывается через objc_msgSend, который обрабатывает и отменяет вызовы на нулевые объекты объектов Objective-C.

Блоки являются переменными, а не методами. Вы можете ожидать, что одни и те же вещи из свойства блока, чем вы можете, из свойства int. Они такие же, как у вас был класс Block, на котором был метод invoke, и вы подклассифицировали его каждый раз, когда вам нужно было что-то другое, за исключением того, что компилятор выполняет всю часть подкласса.

+2

Я считаю, что интерпретатор выполняет это действие: 'view.doneSwipingBlock()' -> 'nil .doneSwipingBlock() '->' [nil doneSwipingBlock]() '->' nil() '' ** crash'. –

+0

Спасибо за быстрый ответ. Таким образом, с блоками я не могу найти что-то похожее на требуемое делегат, где объект CustomView должен установить doneSwipingBlock block.Если у меня есть условие if (view.doneSwipingBlock), то я могу создать объект CustomView без doneSwipingBlock. Есть ли способ заставить заставить doneSwipingBlock аналогично требуемому делегату или я должен использовать только делегаты? – Ezio

+0

Да @IanMacDonald, свойство на объекте nil возвращает nil в соответствии с правилами Objective-C и вызывает nil-сбои для блочных правил. – zneak

Смежные вопросы