はじめに
つい最近、文字列からセレクタを作成してメソッドを呼び出すというのをやりました。検索すると引数なしのメソッドの書き方はすぐ見つかったのですが、引数ありの書き方が見当たらない...ということでその辺りについて書きます。
引数なしの場合
引数なしの場合は下記のように書きます。
perform(Selector("testAction"))
@objc
private func testAction() {
print("testAction")
}
Selectorの呼出がObjective-C方式なので呼び出すメソッドには@objc
が必須です。
Selectorを呼び出す前に下記のようにメソッドがあるかチェックを入れたほうがいいと思います。
let selector = Selector("testAction")
if responds(to: selector) {
perform(selector)
}
引数ありの場合
引数なしの場合は単純ですが、引数があると少し苦労します。(小一時間悩みました...)
@objc
private func testAction(value: String) {
print("testAction value=\(value)")
}
上記のようなメソッドを呼び出す場合perform(Selector("testAction:"), with: "value")
で呼び出せるかと思ったのですが、これではダメなようです。
上記のメソッドを呼び出すには下記のようになります。
let selector = Selector("testActionWithValue:")
if responds(to: selector) {
perform(selector, with: "value")
}
testActionWithValue:
というようにObjective-Cの形式で書いてあげなければいけないようです。
その他呼び出し色々
引数ラベルなし
let selector = Selector("testAction:")
if responds(to: selector) {
perform(selector, with: "value")
}
@objc
private func testAction(_ value: String) {
print("testAction value=\(value)")
}
引数複数
let selector = Selector("testActionWithValue1:value2:")
if responds(to: selector) {
perform(selector, with: "value1", with: "value2")
}
@objc
private func testAction(value1: String, value2: String) {
print("testAction value1=\(value1) value2=\(value2)")
}
引数に数値
let selector = Selector("testActionWithIntValue:")
if responds(to: selector) {
perform(selector, with: NSNumber(value: 10))
}
@objc
private func testAction(intValue: NSNumber) {
print("testAction intValue=\(intValue.intValue)")
}
最後に
文字列でのメソッド呼び出しについて書きましたが、Selectorを使うなら通常は下記の実装になると思います。
文字列でやると警告出ますし...
let selector = #selector(testAction())
perform(selector)
@objc
private func testAction() {
print("testAction")
}
サーバーなどから通信でメソッド名を取得して呼び出すとかあるかもしれませんが、その場合は文字列ではなく数値でもらってenum切って呼び出すメソッドを切り替えた方がいいと思います。
今回はどうしても文字列でメソッド呼び出したいっていうので、このように書きましたがほぼ使い所はないような気がします...(だから検索しても見当たらないのかも)