【Swift】「#Selector」や「@objc」とは何なのか。セレクタについて深めてみた

「#Selector」や「@objc」とは何なのか。セレクタについて深めてみた

#Selectorって何やねん

Swiftの学習中に「#Selector」や「@objc」の存在に気づきながらも、難しそうだなぁと、自動補完に頼っていました。
でも、そろそろ勉強しておかなければと感じたので、初学者ながら知識をまとめてみました。
間違いや改善案などあれば、本記事にコメントして教えて下さい!

さっそく、下に3つの例をあげてみました。
ヤツ(#Selectorとか@objc)はこんな感じに突如として登場しますよね。

// 例1
button.addTarget(self, action: #selector(somefunction), for: .touchUpInside)

@objc func somefunction() { }
// 例2
let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))

@objc func done() {
        fromBaseTextField.endEditing(true)
        fromBaseTextField.text = "\(baseLists[pickerView.selectedRow(inComponent: 0)])進数"
}
// 例3
Timer.scheduledTimer(timeInterval: 1,
                     target: self,
                     selector: "update",
                     userInfo: nil,
                     repeats: false)

ざっくり、セレクタとは?

結論、
セレクタとは「メソッド名のようなもの」の認識で僕はスッキリしました。

例えば下のようなコードで、
「#selector( done )」を記述するだけで、「done()」という関数が使えます。
難しいことを考えなければ、セレクタは「メソッド名のようなもの」の認識でも良いのかなと思いました。

ButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))

@objc func done() { ... }

セレクタを深ぼってみる

でも、セレクタとメソッド名が全く同じ意味ってことは無いはずです。
もう少し深堀りしてみました。

セレクタ(Selector)は、Objective-Cに存在していた考え方です。
SwiftとObjective-Cの互換性を保つために、(仕方なく?)Swiftでも使用しているイメージです。

セレクタに関して下記の記述もありました。

Objective-C コンパイラは、メソッドを特定する名前をコンパイル時に内部表現に変換します。 この、メソッドの内部表現をセレクタと呼び、メッセージの送受信の裏側では、このセレクタがやり取りされています。

http://wisdom.sakura.ne.jp/programming/objc/objc13.html

書いている日本語が難しいですよね。笑
僕なりの解釈では、「セレクタ=メソッドを特定するための特殊な名前」かなと感じました。

また、下記のような記述もあります。

セレクタは、メソッドの名前を表す型で、これを利用することで、メソッドをそれが属する型とは切り離して扱うことができます。

Swift実践入門 第3版

ここでは、
「セレクタ=メソッドの名前を表す型」と解釈されています。

また、下記の記述もあります。

Objective-Cではメッセージ送信の際、セレクタと呼ばれるデータを使ってメソッドを指定し、その動的な起動を可能にしています。

詳解Swift 第5版

ここでは、
「セレクタ=メソッドを起動させるためのメッセージデータ」と解釈されています。

ここまでを踏まえて頭が爆発しそうですが、
整理すると下記の3つの解釈がありました。
「セレクタ=メソッドを特定するための特殊な名前」
「セレクタ=メソッドの名前を表す型」
「セレクタ=メソッドを起動させるためのメッセージデータ」

とりあえずセレクタは、
メソッドを使うための仕組みってことは分かりますよね。

このセレクタをSwiftでは、TimerやUIBarButtonItemのクラスで使われることが多いらしいです。
Timerでは、タイマー終了時にどんなメソッドを実行するか、
UIBarButtonItemでは、ボタンが押されたら、どんなメソッドを実行するか、
これらをセレクターで指定できるって感じです。

これを踏まえて、
実際の使い方となる、「#selector」や「@objc」についてサラーっと見ていきます。

「#selector」や「@objc」の使い方

「#selector( セレクタ名 )」や、「 Selector( “セレクタ名” )」
の書き方で、セレクタを使用することができます。
使用されるメソッドは、先頭に「@objc」という「Objective-Cの名残りである印」を付けてあげます。

これだけで使用できるので、セレクタの使用感は慣れれば簡単なのですが、
コンパイラチェックがないので、実行してから処理が落ちる可能性もあります。
セレクタ名は絶対に間違えられませんね…

ちなみに、使用感は下のような感じです。

ButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))

@objc func done() { ... }
ButtonItem(barButtonSystemItem: .done, target: self, action: Selector("done"))

@objc func done() { ... }


ということで本記事は、セレクタについてご紹介しました。
#Selectorとは何か、@objcとは何か、少しでも学習のお手伝いになれば幸いです。
本記事を書いている僕自身は、まだSwift初学者のためコードに至らない点が多いと思います。参考程度にご活用下さい。
アドバイスやコードの改善などあれば本記事の最後の部分からコメントしてくださいね。
最後まで読んでいただきありがとうございました!

おすすめSwift書籍

Swiftを学ぶなら、間違いのない2冊はこちら

Xcodeを学ぶなら下の一冊



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です