命名超类"消息"时的Objective-C-Runtime Bug

Joh*_*lph 3 runtime objective-c

我有以下课程:

@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
Run Code Online (Sandbox Code Playgroud)

以下单元测试:

- (void) test
{
    FooMessage* msg = [[FooMessage alloc] init];
    [msg release];
}
Run Code Online (Sandbox Code Playgroud)

EXC_BAD_INSTRUCTION测试将始终失败.FooMessage称它为超类析构函数dealloc,但调用永远不会到达那里.而是,Objective-C运行时将调用解析到另一个位置: StackTrace和反汇编

如果将Message基类重命名为其他类,则不会发生错误,例如AbstractMessage.似乎还有另一个名为class的类Message,其定义不公开.

这是一个错误吗?这里到底发生了什么?我是否违反了任何命名限制(尽管我认为编译器应该警告我)?

这是XCode 3.1.为iPhone OS 3.0编译.

Nik*_*uhe 8

Objectve-C缺乏名称空间的概念.这个问题是众所周知的,通常使用前缀命名空间(如NS Object或MK MapView)来解决.您可以命名您的消息类,JrMessage以避免与命名的(未记录的)类发生冲突Message.

如果编译器知道另一个类,它只会警告你.对于私有的,未记录的类,通常情况并非如此.处理此问题的最佳方法是通过在每个类上使用前缀来避免冲突.这也有助于防止未来的冲突,当Apple为新版本的操作系统添加类时(编译器显然无法警告).

编辑:

进一步调查表明,竞争类来自名为"MIME.framework"的私有框架,至少在iPhone模拟器上:

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
Run Code Online (Sandbox Code Playgroud)

您可能希望在错误报告中添加此信息.