Edited at

Swift:#selectorの使い方


はじめに

#selectorの使い方がわからないままでオレはいいのか?

Timerselector引数に渡すときとかで使うけど,まぁ今は動いているから調べるのは今度でいいか」と後回しにすること早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
}
}


参照