2009-10-05 1 views
2

У меня есть указатель на объектный класс C, на который мне нужно отправить сообщения. Указатель потенциально может быть любым, поэтому мне нужно убедиться, что он будет отвечать на мои сообщения, прежде чем отправлять их. Вот функция, я использую, чтобы сделать проверку:Как узнать, является ли указатель NSObject?

int delegatePreparedForSelector(id delegate, SEL aSelector) { 
    if (delegate 
     && [delegate isKindOfClass:[NSObject class]] 
     && [delegate respondsToSelector:aSelector]) { 
     return YES; 
    } 
    return NO; 
} 

Проблема заключается в том, что иногда указатель делегата является struct objc-object * и я получаю EXC_BAD_ACCESS плохую ошибку доступа, когда я отправить сообщение isKindOfClass.

Есть ли лучший тест, который я должен использовать, чтобы определить, будет ли делегат отвечать на мои сообщения?

ответ

5

Похоже, что ваш делегат удаляется перед вызовом, а не что-то, что обязательно связано с этим кодом.

Кроме того, вы можете принудительно реализовать реализацию протокола по параметру так: id<MyDelegateProtocol> delegate вместо того, чтобы просто использовать пустой идентификатор.

+0

В этом проблема. Когда делегат освобождается и устанавливается на 'nil', для его типа устанавливается значение' struct objc_object * ', которое я видел в отладчике. – kubi

+0

Если делегат был равен нулю, вышесказанное не сработало бы. – bbum

+1

nil отличается от deallocated – slf

-1

указатель делегат, указывающий на тип структура objc_object вызывая проблемы сбивает с толку, так как все объекты в Obj-C имеют тип (рытье в OBJ-с объекта):

struct objc_object 
{ 
    struct objc_class *isa; 
    /* extra stuff */ 
}; 

Символ * Isa указывает на класс .. какой-либо класс. Таким образом, объект, который вы устанавливаете как делегат, может просто не существовать или указывать на плохую память.

+0

Вы не можете поймать сигнал ('EXC_BAD_ACCESS'), используя @try. –

+0

woops. ты прав. то ему просто придется вынести это и отследить, где бы ни была ошибка. – pxl

6

Подождите, вы действительно имеете в виду, что указатель может быть чем угодно? Как void *, указывающий на кусок необработанной памяти malloc'ed или объект objc_object, который не является результатом NSObject? Если это действительно так, то нет возможности сделать эту работу безопасно. Это эквивалентно высказыванию «Без разыменования этого указателя, как я могу знать, что он безопасен для разыменования?» Единственный способ состоит в том, чтобы иметь априорное знание о том, что все, что передало его вам, не передало вам плохой указатель.

Вы можете попытаться написать некоторый код обработчика сигнала для очистки EXEC_BAD_ACCESS, но в конечном итоге он будет работать медленно, плохо и маскировать множество других реальных ошибок. Реально у вас либо есть некоторые ограничения на то, что вы проходите, либо вам нужно перепроектировать эту часть вашего проекта.

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

  • Нет связанных вопросов^_^