Ошибка Objective-C-Runtime при именовании суперкласса «Сообщение» - PullRequest
3 голосов
/ 17 мая 2010

У меня есть следующий класс иерархии:

@interface Message : NSObject {}
@end

@implementation Message
- (void) dealloc
{
    // I won't be called
    [super dealloc];
}
@end

@interface FooMessage : Message {}
@end

@implementation FooMessage
- (void) dealloc
{
    // should call Message - dealloc
    [super dealloc];
}
@end

И следующий юнит-тест:

- (void) test
{
    FooMessage* msg = [[FooMessage alloc] init];
    [msg release];
}

Тест всегда будет неудачным с EXC_BAD_INSTRUCTION. FooMessage называет это деструктором суперкласса в dealloc, но вызов туда никогда не поступает. Вместо этого среда выполнения Objective C разрешает вызов в другое место: StackTrace and disassembly

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

Это ошибка? Что на самом деле здесь происходит? Нарушаю ли я какие-либо ограничения именования (хотя я думаю, что компилятор должен предупредить меня об этом)?

Это XCode 3.1. компиляция для iPhone OS 3.0.

1 Ответ

8 голосов
/ 17 мая 2010

В Objectve-C отсутствует концепция пространств имен. Эта проблема хорошо известна и обычно решается с помощью префиксных пространств имен (например, NS Object или MK MapView). Вы можете назвать свой класс сообщений JrMessage, чтобы избежать конфликта с (недокументированным) классом с именем Message.

Компилятор может предупредить вас, только если узнает о другом классе. В случае частных недокументированных классов это часто не так. Лучший способ справиться с этим - избегать конфликтов, используя префикс для каждого класса. Это также помогает против будущих столкновений, когда Apple добавляет классы в новую версию ОС (о которой компилятор явно не мог предупредить).

Edit:

Дальнейшие исследования показывают, что конкурирующий класс происходит из частного фреймворка с именем "MIME.framework", по крайней мере, на iPhone Simulator:

NSLog(@"Message class: %@", [[NSBundle bundleForClass:NSClassFromString(@"Message")] bundlePath]);

... Message class: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk/System/Library/PrivateFrameworks/MIME.framework

Возможно, вы захотите добавить эту информацию в ваш отчет об ошибке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...