web-dev-qa-db-ja.com

Swift 2.2セレクター構文の理解-#selector()

プロジェクトの構文をSwift 2.2(xCodeが自動的に行うのに役立ちます)に切り替えています。ただし、新しい#selector()構文は理解できません。

例として:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, 
             selector: #selector(MyVC.timerCalled(_:)), //new selector syntax!
             userInfo: nil, repeats: true)

これにはセレクター#selector(MyVC.timerCalled(_:))があります

_:は何を意味しますか?このセレクターに他の変数を追加できますか?言ってください、#MyVC.timerCalled(_:whateverVar)

以前のバージョンのSwiftの文字列ベースの実装とは対照的に、この構文の違いに関する一般的な情報は大歓迎です。

36
Anthony Dito

括弧内のビットは、必要なセレクタの引数リストを識別するためのメカニズムです。

Swift Evolutionの Generalized Naming 提案をご覧になることをお勧めします。パラメーターラベルのみが異なる多くの関数があり、それらを参照する必要がある場合について説明します。そのドキュメントの例は次のとおりです。

extension UIView {
  func insertSubview(view: UIView, at index: Int)
  func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
  func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}

それらのいずれかの関数値を取得したい場合、結果はあいまいです:

let fn = someView.insertSubview // ambiguous: could be any of the three methods

実装される解決策は、必要なものを明確にするために関数値を生成するコードに型情報なしで引数ラベルを追加することです。

let fn = someView.insertSubview(_:at:)
let fn1 = someView.insertSubview(_:aboveSubview:)

かっこでラベルがどのように追加されるかを確認しますか?

この提案は、あなたの質問に最も直接当てはまるもので役割を果たしました。

メソッドのObjective-Cセレクターの参照

この特定の場合、参照したいセレクタはtimerCalled:です。これは、ラベルのない1つのパラメータの関数です。したがって(_ :)。アンダースコアは、ラベルが指定されていないこととコロンを意味します。

31
Scott Thompson

Swift 2.2では、非推奨のStringifiedセレクターがあります。Swift 2.0では、セレクターを文字列(つまり"buttonClicked")として記述します。このアプローチの欠点は、コンパイル時にメソッドが実際に存在するかどうかをコンパイラがチェックできないことです(スペルを間違えたとしても)。

EX:1

func buttonClicked(){
}

したがって、新しいアプローチの上記のメソッドは#selector(buttonClicked)として呼び出すことができます

EX:2

func buttonClicked(stringValue : String){
}

したがって、新しいアプローチの上記のメソッドは#selector(buttonClicked(_:))として呼び出すことができます

EX:

func buttonClicked(stringValue : String, indexValue : Int){
}

したがって、新しいアプローチのパラメーターを使用した上記のメソッドは、#selector(buttonClicked(_:indexValue:))として呼び出すことができます。

19

#selectorを使用してSwift 3のボタンにターゲットを追加するための以下のコードを検討してください

button.addTarget(self, action: #selector(self.buttonAction(sender:)),
                       for: UIControlEvents.touchUpInside)

 func buttonAction(sender:UIButton!){

 }

この構文は、Swift 3への移行時に機能しました

9
Ankit

これは、ドキュメントでSwiftメソッドシグネチャが表現される方法であり、引数リストでメソッドを表現する#selector()構文などの新しい言語機能で使用されるようになりました。

各コロン(:)はメソッドパラメーターを表します。名前付きパラメーターの場合、コロンの前に外部パラメーター名が付きます。名前のないパラメータには、アンダースコア(_)が使用されます。

たとえば、MyVC.timerCalled(_:))は、MyVC型のメソッドに名前のないパラメーターが1つあり、次のように宣言される場合があることを示します。

func timerCalled(timer: NSTimer) { ... }

timer内部パラメーター名であることに注意してください。デフォルトではメソッドの最初のパラメーターには名前がありません)

タイプ(例ではMyVC)は、#selector()宣言と同じスコープ内にある場合は省略できます。

より複雑な例は次のようになります。

let sel = #selector(aMethodWithSeveralParameters(_:secondParam:thirdParam:))

...

func aMethodWithSeveralParameters(firstParam: Int, secondParam: Int, thirdParam: Int) { ... }
8
Stuart