为什么我们不能将C字符串用作SEL?

时间:2012-05-28 18:32:01

标签: objective-c methods selector objective-c-runtime

所以,我一直在讨论objc-runtime(惊喜),我找到了一个有趣的代码块here

const char *sel_getName(SEL sel) {
#if SUPPORT_IGNORED_SELECTOR_CONSTANT
    if ((uintptr_t)sel == kIgnore) return "<ignored selector>";
#endif
    return sel ? (const char *)sel : "<null selector>";
}

所以,这告诉我的是SEL相当于一个C字符串,在每种习惯中。对包含@selector(addObject:)的SEL的前16个字节执行十六进制转储,将提供以下内容:

  

61 64 64 4F 62 6A 65 63 74 3A 00 00 00 00 00 00

这等于C字符串addObject:

话虽如此,当我使用C字符串作为选择器时,为什么这段代码会崩溃?

SEL normalSEL  = @selector(addObject:);
SEL cStringSEL = (SEL) "addObject:";

NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", nil];

[arr performSelector:normalSEL withObject:@"3"];
[arr performSelector:cStringSEL withObject:@"4"];

NSLog(@"%@", arr);

据我所知,选择器的内容是相同的,为什么第二个的崩溃会出现以下错误信息?

  

***由于未捕获的异常'NSInvalidArgumentException'而终止应用,       原因:' - [__ NSArrayM addObject:]:无法识别的选择器发送到实例       0x101918720'***

1 个答案:

答案 0 :(得分:22)

选择器是实习C字符串,并按地址而不是其内容进行比较。字符串内容仅用于转换为外部字符串表示形式。进行实习以提高性能 - 当运行时查找与选择器匹配的方法实现时,它可以直接比较选择器指针,而不是解除引用每个指针并比较字符。