Selector
概要
Selector とは、簡単にいうと ランタイムに利用するメソッドの識別子 である。実行するメソッドをランタイムに 選択 (select) する ための名前であり、ソースコードのコンパイル後にメソッドの識別用に利用される識別子、あるいはコンパイル後のメソッドの内部表現とも捉えられる
主に、関数ポインタのように、動的にメソッドを特定したいケースや、Swift から Objective-C のメソッドを利用したいケース (Target-Action パターンの利用など) で利用する
実態は Objective-C だと SEL 構造体、Swift だと Selector 構造体となっている
https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html
https://developer.apple.com/documentation/swift/using_objective-c_runtime_features_in_swift
使い方
Selector の取得
Objective-C では、@selector という Objective-C のコンパイラディレクティブが利用できる
Swift だと #selector という Expression が利用できる (Swift 2 くらいだと @selector がまだ使えた気がする)
Selector の利用
Selector を引数にとるメソッドとしては、perform(_:) メソッドが存在する。これは、receiver に aSelector というメッセージを直接送信するのと同義。
code:swift
func perform(_ aSelector: Selector!) -> Unmanaged<AnyObject>!
code:objc
- (id)performSelector:(SEL)aSelector;
これは、Swift においてドット記法でメソッドを呼び出すのと同じ。例えば、以下は全く同一。
code:swift
let aClone = anObject.copy()
let aClone = anObject.perform(#selector(MyObject.copy)).takeRetainedValue()
perform(_:) メソッドは、送信するメッセージが実行時まで決まらない 場合に利用できる。しかし、戻り値がコンパイル時に保障されないというリスクがある。
https://developer.apple.com/documentation/objectivec/nsobjectprotocol/1418867-perform
Objective-C Runtime と Selector
Objective-C Runtime では SEL 型の構造体として表現される
Selector は C の文字列であり、Objective-C Runtime によって登録、ないしマッピングが行われる
コンパイラによって生成される Selector は、クラスのロード時にランタイムによって自動的にマッピングされる
既存の Selector の取得には sel_registerName を利用する
Selector を利用するためには、sel_registerName からの戻り値を使うか、Objective-C コンパイラディレクティブの @selector を利用する
sel_registerName の定義は以下のようになっている。引数の str には登録したい Selector 名を渡す。
code:swift
func sel_registerName(_ str: UnsafePointer<Int8>) -> Selector
code:objc
SEL sel_registerName(const char *str);
https://developer.apple.com/documentation/objectivec/sel
Objective-C のメソッド呼び出しについてもっと知りたい場合には以下が参考になりそう
https://qiita.com/kunichiko/items/a0b8ce64518fbf3eac0a