はじめに
ナビゲーションバーの戻るボタンをタップ時に、「ダイアログを表示 -> キャンセルの場合、遷移させない」という処理を実装したかったのですが、デフォルトで実装されている戻るボタン (backBarButtonItem
) をカスタマイズする方法ではうまくいきませんでした。
ダメだった方法
// MARK: onTapBackButton は呼ばれない
let backButton = UIBarButtonItem(image: chevronLeftImage, style: .plain, target: self, action: #selector(onTapBackButton(_:)))
navigationItem.backBarButtonItem = backButton
そこでデフォルトの戻るボタンは使わず、新たにボタンを作成し leftBarButtonItem
として配置するという方法で実装しました。
環境
- Xcode 11.5
- Swift 5.2.4
デフォルトの戻るボタンを置き換える
特定の ViewController のみボタンを置き換えた場合、デフォルトの戻るボタンと見た目が変わってしまうため、今回は全てのボタンを置き換えます。
すべての画面で読み込む親クラスとして CommonViewController
を生成し実装していきます。
コード全体
class CommonViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
backButton()
}
private func backButton() {
let currentViewController = String(describing: type(of: self))
guard !currentViewController == "FirstViewController" else {
return
}
let chevronLeftImage: UIImage? = UIImage(systemName: "chevron.left")
let backButton = UIBarButtonItem(image: chevronLeftImage, style: .plain, target: self, action: #selector(onTapBackButton(_:)))
navigationItem.leftBarButtonItem = backButton
}
@objc
func onTapBackButton(_ sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
}
最初の画面 (FirstViewController
) では戻るボタンを非表示にします。
// 現在の ViewController 名を取得
let currentViewController = String(describing: type(of: self))
guard !currentViewController == "FirstViewController" else {
return
}
新たにボタンを生成し leftBarButtonItem
に登録します。
leftBarButtonItem
が表示されている場合、デフォルトの戻るボタンは非表示になります。
let chevronLeftImage: UIImage? = UIImage(systemName: "chevron.left")
let backButton = UIBarButtonItem(image: chevronLeftImage, style: .plain, target: self, action: #selector(onTapBackButton(_:)))
navigationItem.leftBarButtonItem = backButton
タップ時に呼び出されるアクションに、前画面へ遷移する処理を記述します。
@objc
func onTapBackButton(_ sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
特定の ViewController で処理をカスタマイズする
処理をカスタマイズしたい ViewController で onTapBackButton
を override します。
@objc
override func onTapBackButton(_ sender: UIBarButtonItem) {
// TODO: ここに処理を記述
navigationController?.popViewController(animated: true)
}
参考
- [Xcode - navigationBarの戻るボタンでの画面遷移をキャンセルしたい|teratail] (https://teratail.com/questions/274061)
- [ios - Execute action when back bar button of UINavigationController is pressed - Stack Overflow] (https://stackoverflow.com/questions/27713747/execute-action-when-back-bar-button-of-uinavigationcontroller-is-pressed/37230710)