Как мне узнать, является ли указатель NSObject? - PullRequest
2 голосов
/ 05 октября 2009

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 06 октября 2009

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

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

5 голосов
/ 06 октября 2009

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

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

0 голосов
/ 06 октября 2009

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

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

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

...