記事概要
「戻るボタンをタップした時に○○する」という戻る以外の処理を挟むという仕様を実現する際のアプローチの整理。
- やりがちNGパターン
- 一部対応パターン
- 一括対応パターン(UINavigationController単位)
- まとめ
やりがちNGパターン
backBarButtonItemのactionは無視されるため動作しません。
.swift
navigationItem.backBarButtonItem = UIBarButtonItem(title: "戻る", style: .plain, target: nil, action: #selector(doSomething))
@objc
func doSomething() {
// 戻るボタンの動作処理
}
一部対応パターン
navigationItemのleftBarButtonItemを利用する
この方法はかなりネット上に広がってる方法です。
一部対応.swift
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "戻る", style: .plain, target: nil, action: #selector(doSomething))
@objc
func doSomething() {
// 戻るボタンの動作処理
}
良い点
- UIViewControllerから指定もできるので、見通しが良い。
問題点
- backBarButtonItemとleftBarButtonItemでボタン位置が若干変わる。
- (iOS7の時のような)HIGのガイドラインが変わるような変更があった場合、実装箇所において各画面で修正が必要。
一括対応パターン(UINavigationController単位)
UINavigationControllerのサブクラスを実装し、UINavigationBarDelegateを採用する
UINavigationController.navigationBar
のUINavigationBarDelegate
を直接手動で設定できません。(実行時エラーになります)
また、UINavigationController.navigationBar
はget-only
なので以下に実装になります。
.swift
final class OriginalNavigationController: UINavigationController, UINavigationBarDelegate {
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
// 戻るボタンの動作処理
return false
}
}
良い点
- 一括で対応できるので、共通仕様として実装する場合はシンプルに実現できる。
問題点
- 特定の1画面に対してだと、少し大袈裟な実装。
- 特定の条件の画面に対してだと、画面特定が泥臭い感じになり、拡張時に考慮する必要がある。
- UIViewControllerから離れているので、どこで制御しているか分かりにくい。(半年後忘れているかも?)
- UIViewControllerに関連するロジックを実装する必要がある場合も設計上問題が出がち。
まとめ
今回提示したアイデアとしては2つですが、一長一短なので状況に応じて対応かなと思います。
個人的にはiOS7の時にデザイン修正がちょっとした作業量になった経験から、前者を実装するのであれば特定の条件の画面のみ戻るボタンで実現するというアプローチ以外に機能実現する方法を検討し、回避するのも手だと考えています。