セレクタ文字列リテラルのターゲットとしてジェネリック関数を使用することはできません。なんで?セレクターには、ターゲットの引数の型に関する情報は含まれていません。
- セレクターのターゲットの名前 (メソッド名) 、
- そして、(暗黙的に)セレクターのターゲットの引数の数。
そのため、Swift は、同じ名前と同じ数の引数を持つ非ジェネリック関数をセレクターのターゲットとして使用することさえ許可しません。これは、セレクターが使用するターゲットに関して競合が発生するためです。
たとえば、次の (遊び場) の例を考えてみましょう。
class Foo : UIView {
var button = UIButton()
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
button.addTarget(self, action: "eventFired:", forControlEvents: UIControlEvents.TouchUpInside)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func eventFired(sender: UIButton){
print("event fired!")
}
}
let foo = Foo()
foo.button.sendActionsForControlEvents(.TouchUpInside)
/* event fired! */
これは意図したとおりに機能しますが、次のメソッドをFoo
クラスに追加してみてください。
class Foo : UIView {
// ...
func eventFired(nothingToDoWithAButton: Int){
print("another event fired!")
}
}
上記と同じ例では、呼び出すターゲット メソッドに関してセレクターが競合しているため、エラーが発生します。
let foo = Foo()
foo.button.sendActionsForControlEvents(.TouchUpInside)
/* error ... */
エラー: eventFired
Objective-C セレクター ' ' を持つメソッド ' 'eventFired:
は、同じ Objective-C セレクターを持つ前の宣言と競合します ...
最後に、上記の追加メソッドを次のように変更すると、
class Foo : UIView {
// ...
func eventFired(nothingToDoWithAButton: Int, someBool: Bool){
print("another event fired!")
}
}
次に、セレクターは、引数の数の違いによりeventFired(:UIButton)
2 つのメソッド間で異なる可能性があるため、予想どおり、そのターゲットを見つけます。eventFired
上記から、セレクター/セレクター リテラルは、現在の形式では原始的すぎて使用できず、明確にジェネリック ターゲットを識別できないことは明らかです。セレクターには、同じ名前/同じ数の引数のターゲット間で区別できるように、ターゲット引数の型の知識を含める必要があります。
最後に、文字列リテラルとしての現在の形式のセレクターは、Swift 2.2 で非推奨になり、Swift 3.0 で削除され、新しい式構文が優先されることに注意して#selector
ください。以下を参照してください。
(以下の追加書き込みOP:sコメントを編集)
ターゲットに参照型 ( ) からのさまざまなシグナルをキャッチさせ、引数...(:AnyObject)
にラップされている型に応じてイベントを処理させることで、やや一般的なセレクター ターゲットを模倣することができます。AnyObject
class Foo : UIView {
var button = UIButton()
var sw = UISwitch()
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
button.addTarget(self, action: "eventFired:", forControlEvents: .TouchUpInside)
sw.addTarget(self, action: "eventFired:", forControlEvents: .ValueChanged)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func eventFired(sender: AnyObject){
switch(sender) {
case is UIButton: print("button event fired!")
case is UISwitch: print("switch event fired!")
case _: print("unknown event fired")
}
}
}
let foo = Foo()
foo.button.sendActionsForControlEvents(.TouchUpInside)
/* button event fired! */
foo.sw.sendActionsForControlEvents(.ValueChanged)
/* switch event fired! */