Swift で @selector() を使うには?質問する

Swift で @selector() を使うには?質問する

NSTimerインを作成しようとしていますSwiftが、問題が発生しています。

NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)

test()同じクラスの関数です。


エディターでエラーが発生します:

指定された引数を受け入れる 'init' のオーバーロードが見つかりませんでした

selector: test()に変更するとselector: nilエラーは消えます。

私はもう試した:

  • selector: test()
  • selector: test
  • selector: Selector(test())

しかし、何も機能せず、参考資料の中に解決策を見つけることができません。

ベストアンサー1

Swift自体はセレクタを使用しません。Objective-C でセレクタを使用するいくつかのデザイン パターンは、Swift では動作が異なります。(たとえば、プロトコル タイプやis/asテストでは の代わりにオプション チェーンを使用しrespondsToSelector:、型やメモリの安全性を高めるために、 の代わりに可能な限りクロージャを使用しますperformSelector:。)

しかし、タイマーやターゲット/アクション パターンなど、セレクターを使用する重要な ObjC ベースの API はまだ数多くあります。Swift は、Selectorこれらを操作するための型を提供します (Swift はこれを ObjC の型の代わりに自動的に使用しますSEL)。

Swift 2.2 (Xcode 7.3) 以降 (Swift 3 / Xcode 8 および Swift 4 / Xcode 9 を含む):

Selector式を使用して、Swift 関数型から を構築できます#selector

let timer = Timer(timeInterval: 1, target: object,
                  selector: #selector(MyClass.test),
                  userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
                 for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
             with: button, with: otherButton)

このアプローチの素晴らしい点は、関数参照がSwiftコンパイラによってチェックされるため、#selector実際に存在し、セレクタとして使用できるクラス/メソッドのペアでのみ式を使用できることです(以下の「セレクタの可用性」を参照)。また、必要に応じて関数参照を自由に特定できます。Swift 2.2+ 関数型命名規則

(これは実際には ObjC のディレクティブよりも改善されています@selector()。コンパイラの-Wundeclared-selectorチェックでは、名前付きセレクターが存在することのみが検証されるからです。渡す Swift 関数参照では、#selector存在、クラス内のメンバーシップ、および型シグネチャがチェックされます。)

式に渡す関数参照については、いくつか追加の注意事項があります#selector

  • 同じ基本名を持つ複数の関数は、前述のパラメータラベルを使用して区別することができます。関数参照の構文(例:insertSubview(_:at:)insertSubview(_:aboveSubview:))。ただし、関数にパラメータがない場合、as関数の型シグネチャを使用してキャストを使用することが、その関数を明確にする唯一の方法です (例:foo as () -> ()foo(_:))。
  • Swift 3.0 以降では、プロパティの getter/setter ペアに特別な構文があります。たとえば、 の場合、または をvar foo: Int使用できます。#selector(getter: MyClass.foo)#selector(setter: MyClass.foo)

一般的な注意事項:

#selectorが機能しないケースと命名:セレクターを作成するための関数参照がない場合があります (たとえば、ObjC ランタイムで動的に登録されたメソッドなど)。その場合は、Selector文字列から を構築できます。例: Selector("dynamicMethod:")— ただし、コンパイラの妥当性チェックは失われます。これを行うときは、各パラメーターのコロン ( ) を含む ObjC 命名規則に従う必要があります:

セレクターの可用性:セレクターによって参照されるメソッドは、ObjC ランタイムに公開されている必要があります。Swift 4 では、ObjC に公開されるすべてのメソッドの宣言の前に@objc属性を付ける必要があります。(以前のバージョンでは、場合によってはその属性を無料で取得できましたが、現在は明示的に宣言する必要があります。)

privateシンボルもランタイムに公開されないことに注意してください。メソッドには少なくともinternal可視性が必要です。

キーパス:これらはセレクターと関連していますが、まったく同じではありません。Swift 3でも、これらには特別な構文があります。例: chris.valueForKeyPath(#keyPath(Person.friends.firstName))SE-0062詳細はこちらをご覧ください。KeyPathSwift 4 のものしたがって、適切な場合は、セレクターではなく適切な KeyPath ベースの API を使用していることを確認してください。

セレクターの詳細については、以下を参照してください。Objective-C API とのやり取りCocoa と Objective-C で Swift を使用する。

注: Swift 2.2 より前は にSelector準拠していたためStringLiteralConvertible、セレクターを受け取る API に裸の文字列が渡される古いコードが見つかる場合があります。 を使用するようにするには、Xcode で「現在の Swift 構文に変換」を実行する必要があります#selector

おすすめ記事