はじめに
ただどう動くんだろう?って言うだけの話で実用性は皆無です
なんか UIButton に謎のアクションを付けれたというお話です。
環境
- Xcode 11.4
- iPhone 11 Pro Max (13.4)
実装
- StoryboardでFirstViewControllerとSecondViewControllerを用意する
- FirstVCにボタンをのせる
- IBActionでボタンのアクションをFirstVCに紐付ける(
tappedFirst(_ sender: Any)
) - SecondVCにFirstVCのボタンをコピペする
- IBActionでボタンのアクションをSecondVCに紐付ける(
tappedSecond(_ sender: Any)
)
こんな感じ

final class FirstViewController: UIViewController {
@IBAction private func tappedFirst(_ sender: Any) {
print("First")
let vc = storyboard?.instantiateViewController(identifier: "Second")
navigationController?.pushViewController(vc!, animated: true)
}
}
final class SecondViewController: UIViewController {
@IBAction private func tappedSecond(_ sender: Any) {
print("Second")
}
}
現象
Storyboard で SecondVC のボタンを確認すると...
こうなる!

tappedFirst
がついてる。シュミレータで SecondVC のボタンを押下してみると Second
と print 表示される。(FirstVCの tappedFirst(_)
が呼ばれたりはしない)unrecognized selector でクラッシュもしない
調査
下記のようにボタンのカスタムクラスを作り FirstVC と SecondVC のボタンに継承させる。
class CustomButton: UIButton {
override func sendActions(for controlEvents: UIControl.Event) {
print("sendActions")
super.sendActions(for: controlEvents)
}
override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
print("sendAction")
super.sendAction(action, to: target, for: event)
}
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
print("beginTracking")
return super.beginTracking(touch, with: event)
}
override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
print("endTracking")
return super.endTracking(touch, with: event)
}
override func cancelTracking(with event: UIEvent?) {
print("cancelTracking")
super.cancelTracking(with: event)
}
override func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event) {
print("addTarget")
super.addTarget(target, action: action, for: controlEvents)
}
}
FirstVC表示時のログ
addTarget
FirstVCのボタン押下時のログ
beginTracking
endTracking
sendAction
First
addTarget
最後の addTarget は SecondVC 表示時のやつ
SecondVC表示時のログ
addTarget
アクションは2つあるけど1回しか呼ばれない
SecondVCのボタン押下時のログ
beginTracking
endTracking
sendAction
Second
調査結果
SecondVC のボタンの addTarget
が一回しか呼ばれていないことからそもそも tappedFirst
のアクションは追加されていないみたい

Storyboardでアクションを付けたボタンを他画面からコピペすれば動作しない謎のアクションを付けることができる!これをすれば他の開発者を惑わすこともたやすいだろう
さいごに
実装中に謎のアクションをみつけたので調べてみた結果です。活かせる場はあるだろうか