13

だから、私は再びobjc-runtimeをいじり回していて(驚きの驚き)、ここで興味深いコードのブロックを見つけました:

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、あらゆるマニエリスムにおいて、aはCストリングと同等であるということです。を含むSELの最初の16バイトの16進ダンプを実行すると@selector(addObject:)、次のようになります。

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);

私の知る限り、セレクターの内容は同じですが、なぜ2番目のセレクターで次のエラーメッセージが表示されてクラッシュするのでしょうか。

***キャッチされなかった例外'NSInvalidArgumentException'が原因でアプリを終了しています、理由:'-[__ NSArrayM addObject:]:認識されないセレクターがインスタンス0x101918720に送信されました'***

4

1 に答える 1

22

セレクターはインターンされたC文字列であり、内容ではなくアドレスによって比較されます。文字列の内容は、外部の文字列表現との間の変換にのみ使用されます。インターンは、パフォーマンスを向上させるために行われます。ランタイムがセレクターに一致するメソッド実装を検索しているときに、各ポインターを逆参照して文字を比較する代わりに、セレクターポインターを直接比較できます。

于 2012-05-28T18:38:32.950 に答える