はじめに
#selector
の使い方がわからないままでオレはいいのか?
「Timer
のselector
引数に渡すときとかで使うけど,まぁ今は動いているから調べるのは今度でいいか」と後回しにすること早5年.Objective-CのライブラリをSwiftに翻訳する仕事に着手し,ついに学ぶ時がきた.
こういう時に見るやつ
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(hoge), // ←コレ
userInfo: nil,
repeats: false)
let button = NSButton(frame: NSRect(x: 0, y: 0, width: 30, height: 20))
button.target = self
button.action = #selector(hoge) // ←コレ
法則
引数なしのメソッド呼び出し
selecter: #selector(Test.callMethod) // シンプルにクラス名.メソッド名でOK
class Test {
@objc func callMethod() {
Swift.print("Hello World")
}
}
※@objc
をつけること
1引数ありのメソッド呼び出し
ノーマル
selecter: #selector(Test.callMethod(name:)) // シンプルにクラス名.メソッド名(引数名:)
class Test {
@objc func callMethod(name: String) {
Swift.print("Hello " + name)
}
}
引数名省略パターン
selecter: #selector(Test.callMethod(_:)) // クラス名.メソッド名(_:)
class Test {
@objc func callMethod(_ name: String) {
Swift.print("Hello " + name)
}
}
ラベル付きのパターン
selecter: #selector(Test.callMethod(userName:)) // クラス名.メソッド名(ラベル:)
class Test {
@objc func callMethod(userName name: String) {
Swift.print("Hello " + name)
}
}
いろいろ書いたけど,そのメソッドが一意に定まるときは引数なくてもいいらしい.
複数引数ありのメソッド呼び出し
基本的に引数一個の時の法則はそのままで続けて書く
selecter: #selector(Test.callMethod(word:name:)) // クラス名.メソッド名(引数名1:引数名2:)
class Test {
@objc func callMethod(word: String, name: String) {
Swift.print(word + " " + name)
}
}
できないこと
#selector
でメソッドを渡す時に一緒に引数を渡すことはできない.
あくまで受け取り先が指定している形式でしか渡せない.
Selector
を引数にとるメソッドを作る
ちょっとした応用として,Apple標準クラスのextension
を書くときにSelector
を引数にとるメソッドを書ける.
例
extension NSButton {
public func setAction(selector: Selector) {
self.action = selector
}
}