LoginSignup
7
7

More than 3 years have passed since last update.

【Swift】ナビゲーションバーの戻るボタンの処理をカスタマイズしたい

Posted at

はじめに

ナビゲーションバーの戻るボタンをタップ時に、「ダイアログを表示 -> キャンセルの場合、遷移させない」という処理を実装したかったのですが、デフォルトで実装されている戻るボタン (backBarButtonItem) をカスタマイズする方法ではうまくいきませんでした。

ダメだった方法
SomeViewController.swift
// 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 を生成し実装していきます。

コード全体
CommonViewController.swift
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) では戻るボタンを非表示にします。

CommonViewController.swift
// 現在の ViewController 名を取得
let currentViewController = String(describing: type(of: self))
guard !currentViewController == "FirstViewController" else {
    return
}

新たにボタンを生成し leftBarButtonItem に登録します。
leftBarButtonItem が表示されている場合、デフォルトの戻るボタンは非表示になります。

CommonViewController.swift
let chevronLeftImage: UIImage? = UIImage(systemName: "chevron.left")
let backButton = UIBarButtonItem(image: chevronLeftImage, style: .plain, target: self, action: #selector(onTapBackButton(_:)))
navigationItem.leftBarButtonItem = backButton

タップ時に呼び出されるアクションに、前画面へ遷移する処理を記述します。

CommonViewController.swift
@objc
func onTapBackButton(_ sender: UIBarButtonItem) {
    navigationController?.popViewController(animated: true)
}

特定の ViewController で処理をカスタマイズする

処理をカスタマイズしたい ViewController で onTapBackButton を override します。

SomeViewController.swift
@objc
override func onTapBackButton(_ sender: UIBarButtonItem) {
    // TODO: ここに処理を記述
    navigationController?.popViewController(animated: true)
}

参考

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7