【发布时间】:2012-06-03 01:52:59
【问题描述】:
所以,我又搞砸了 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'***
【问题讨论】:
-
请注意,您可以使用
sel_registerName()将 C 字符串转换为祝福的 SEL(它基本上在幕后使字符串唯一,以保留后续指针标识)。另请注意,您永远不应直接依赖 SEL 是char*。它可能永远都是,但这并不能使假设正确。
标签: objective-c methods selector objective-c-runtime