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詳細はこちらをご覧ください。KeyPath
Swift 4 のものしたがって、適切な場合は、セレクターではなく適切な KeyPath ベースの API を使用していることを確認してください。
セレクターの詳細については、以下を参照してください。Objective-C API とのやり取りCocoa と Objective-C で Swift を使用する。
注: Swift 2.2 より前は にSelector
準拠していたためStringLiteralConvertible
、セレクターを受け取る API に裸の文字列が渡される古いコードが見つかる場合があります。 を使用するようにするには、Xcode で「現在の Swift 構文に変換」を実行する必要があります#selector
。