🍣

#selector の中の関数に、パラメータを使ってはいけない理由

2022/05/06に公開

画面の中心にボタンを置き、そのボタンの繋がったクリック関数に
パラメータを使用してみます

しかし、実際にそのボタンをクリックすると
number 5がプリントされてなく
number 4527816368がプリントされてしまいました

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(type: .system)
        button.setTitle("Click me", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

    @objc func buttonTapped(number: Int = 5) {
        print("number", number) // number 4527816368
    }

}

addTarget()の第一のパラメータ

func buttonTapped()を以下のように修正して、パラメータをもっと詳しくみてみましょう

@objc func buttonTapped(first: Any) {
	print("first", first)
}

そしてボタンをクリックしたら

このようなものがプリントされました
どうやらUIButtonそのものがプリントされました

文章の冒頭の4527816368は、その返すべきのUIButtonが、Intに変換され
<UIButton>4527816368
のような数字が返されました

addTarget()の第二のパラメータ

もういっちょ試して、第二のパラメータを加えてみると

@objc func buttonTapped(first: Any, second: Any) {
	print("second", second)
}

今回はタッチ事件が返したようです

まとめ

addTarget()が使用した#selector()には
独自のパラメータが限定されたようです

  • 第一のパラメータはUIButton
  • 第二のぱあメータはUIEvent

以上の事実を踏まえて、コードの可読性を向上してみます

@objc func buttonTapped(button: UIButton, event: UIEvent) {
	print(button)
	print(event)
}

結論

場合によりますが
少なくとも、addTarget()では
#selector()にカスタイムパラメータの使用は不可のようです

Discussion