6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOS (その2)Advent Calendar 2018

Day 23

Selectorで文字列からメソッドを呼び出す(Swift4.2)

Last updated at Posted at 2018-12-22

はじめに

つい最近、文字列からセレクタを作成してメソッドを呼び出すというのをやりました。検索すると引数なしのメソッドの書き方はすぐ見つかったのですが、引数ありの書き方が見当たらない...ということでその辺りについて書きます。

引数なしの場合

引数なしの場合は下記のように書きます。

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切って呼び出すメソッドを切り替えた方がいいと思います。

今回はどうしても文字列でメソッド呼び出したいっていうので、このように書きましたがほぼ使い所はないような気がします...(だから検索しても見当たらないのかも)

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?