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:)
vsなどinsertSubview(_:aboveSubview:)
)を使用して、パラメーターラベルで区別できます。ただし、関数にパラメーターがない場合、関数を明確にする唯一の方法はas
、関数の型シグニチャー(foo as () -> ()
vsなどfoo(_:)
)を持つキャストを使用することです。
- Swift 3.0以降では、プロパティのゲッター/セッターのペアに特別な構文があります。たとえば、を指定すると
var foo: Int
、#selector(getter: MyClass.foo)
またはを使用できます#selector(setter: MyClass.foo)
。
一般的注意事項:
#selector
機能しないケースと命名:セレクターを作成するための関数参照がない場合があります(たとえば、ObjCランタイムに動的に登録されたメソッドを使用する場合)。その場合はSelector
、文字列からを作成できます。たとえばSelector("dynamicMethod:")
、コンパイラの有効性チェックが失われます。その場合:
、各パラメーターのコロン()を含むObjC命名規則に従う必要があります。
セレクターの可用性:セレクターによって参照されるメソッドは、ObjCランタイムに公開する必要があります。Swift 4では、ObjCに公開されるすべてのメソッドの宣言の前に@objc
属性を付ける必要があります。(以前のバージョンでは、場合によってはその属性を無料で取得していましたが、現在は明示的に宣言する必要があります。)
ことを忘れないでくださいprivate
、あまりにも、シンボルが実行時に公開されていません-あなたの方法は、少なくとも持っている必要がありinternal
、視認性。
キーパス:これらはセレクターに関連していますが、セレクターとはまったく同じではありません。例えば:あまりにスウィフト3におけるこれらのための特別な構文が、ありますchris.valueForKeyPath(#keyPath(Person.friends.firstName))
。詳細については、SE-0062を参照してください。KeyPath
Swift 4にはさらに多くのものがあるため、必要に応じて、セレクターの代わりに正しいKeyPathベースのAPIを使用していることを確認してください。
セレクターの詳細については、「CocoaおよびObjective-CでのSwiftの使用」の「Objective-C APIの操作」を参照してください。
注: Swift 2.2より前はにSelector
準拠しStringLiteralConvertible
ていたため、セレクターを取るAPIに裸の文字列が渡される古いコードが見つかる可能性があります。Xcodeで「Convert to Current Swift Syntax」を実行して、を使用するものを取得する必要があり#selector
ます。
selector: test()
呼び出しtest
て、その戻り値をselector
引数に渡します。