発生している問題・知りたいこと
UIBarButtonItemの初期化タイミングによって、actionメソッドが呼ばれないケースがある事がわかりました。
なぜそのケースだけactionメソッドが呼ばれないのか理由を知りたいです。
問題の現象
上のイメージのようにナビゲーションバーに配置された2つのボタンがあり、タップすると各々”OK”、”NG”とデバッグ出力する処理を組み込みましたが、なぜかNGボタンの方だけデバッグ出力されません。
再現方法
Xcode Version 10.3 で試しています。
storyboard
![
storyboardで実装したのはデフォルトのViewControllerにNavigationControllerを追加しただけです。
ソースコード
swift
1import UIKit 2 3class ViewController: UIViewController { 4 5 var okButton: UIBarButtonItem! 6 7 // NGボタンの初期化 8 var ngButton = UIBarButtonItem(title: "NG", style: .plain, target: self, action: #selector(ngButtonTapped(_:))) 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 // OKボタンの初期化 14 okButton = UIBarButtonItem(title: "OK", style: .plain, target: self, action: #selector(okButtonTapped(_:))) 15 16 // navigationItemに2つのボタンをセット 17 self.navigationItem.rightBarButtonItems = [ngButton, okButton] 18 } 19 20 // OKボタンをタップした時のアクション 21 @objc func okButtonTapped(_ sender: UIBarButtonItem) { 22 print("OK!") 23 } 24 25 // NGボタンをタップした時のアクション 26 @objc func ngButtonTapped(_ sender: UIBarButtonItem) { 27 print("NG!") 28 } 29} 30
ご覧のようにOKボタンとNGボタンは初期化の場所を変えています。
NGボタンもviewDidLoad()で初期化すれば想定通り動作するのですが、なぜ既存の位置の初期化ではダメなのか理由を知りたいです。
試したこと
storyboard上でUINavigationControllerを使用せず、Navigation BarとNavigation Item部品を手動で配置して試した所、上記のような初期化位置でも両方デバッグ出力される事を確認しました。
NavigationController配下で自動生成される UIViewController.navigationItemを利用しているのが原因だろうなぁと、薄々感じています。リファレンスにも何かそれらしい事が書いてあるように見えるのですが、google翻訳さんの力を借りても理解できませんでした。
追記情報です
比較の為にNavigationControllerを使わないケースの再現方法を追記します。
NavigationControllerを使わないケース
storyboard
デフォルトのViewControllerにNavigation Bar部品を追加しました。
UINavigationItemはmyNavigationItemという名前でOutlet接続します。
ソースコード
import UIKit class ViewController: UIViewController { @IBOutlet weak var myNavigationItem: UINavigationItem! var okButton: UIBarButtonItem! // NGボタンの初期化 var ngButton = UIBarButtonItem(title: "NG", style: .plain, target: self, action: #selector(ngButtonTapped(_:))) override func viewDidLoad() { super.viewDidLoad() // OKボタンの初期化 okButton = UIBarButtonItem(title: "OK", style: .plain, target: self, action: #selector(okButtonTapped(_:))) // navigationItemに2つのボタンをセット myNavigationItem.rightBarButtonItems = [ngButton, okButton] } // OKボタンをタップした時のアクション @objc func okButtonTapped(_ sender: UIBarButtonItem) { print("OK!") } // NGボタンをタップした時のアクション @objc func ngButtonTapped(_ sender: UIBarButtonItem) { print("NG!") } }
解説
前のケースと違うのは、NavigationControllerによって自動生成されたNavigationItemではなく、storyboard上で手動で付加したものを使った事だけです。
ところが、こちらのケースでは"OK"ボタン"NG"ボタン共に、正しくデバッグ表示されます。
なぜ、最初のケースの"NG"ボタンのactionメソッドだけが機能しないのか知りたいです。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。