1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UINavigationControllerで数個前(n個前)の画面に戻りたいマン

Posted at

概要

様々な画面、様々なパターンでの表示があるアプリを作成中。
UINavigationContollerで画面を制御している状態。
作る物が画面A1に画面Bの処理が完了したら戻ったり、画面A1から画面B更に画面Cに遷移した後画面Cから画面A1に戻ったり。
画面A2から画面Bに行って処理が完了したら画面A2に戻ったり・・・。
何個戻るのか、どこに戻るのか正直わからん状態な状況になってしまった。

で、その解決方法を色々考慮したのでメモ。

とりあえず要件を整理した結果、下記が分かった。

  • 戻る画面は、呼び出し元の画面
  • 呼び出し元の画面は複数ある(画面A1だったり画面A2だったり画面A3だったり)
  • 処理完了後呼び出し元に戻る場合は、遷移順として必ず画面Bを経由する
  • 処理完了後戻らないパターンも実はある

解決方法

とりあえず画面Bを必ず経由するようなので、画面BのViewDidLoadで親ViewController(画面A1等)をSingletonで管理している変数に格納。
これは処理後に、呼び出し元に戻る必要がある場合だけ実行。
それ以外はnilをつっこんでおいた。

AppData.shared.parentViewController = self.navigationController?.viewControllers[(self.navigationController?.viewControllers.count)! - 2]

処理が終わったら呼び出し元に戻る呪文を唱える。

if let parentViewController = AppData.shared.parentViewController {
    AppData.shared.parentViewController = nil
    self.navigationController?.popToViewController(parentViewController, animated: true)
}

うごいた。よかったね。

おまけ

悲しい失敗編

最初実装時、protocolで画面Cとかを閉じるときに画面Bにも閉じろという形で処理をすれば終わりじゃないかと思っていた。

self.navigationController?.popViewController(animated: true)

2画面まではそれで行けたのだが、3画面以降はprotocolで定義した関数が順々に呼び出されるもpopViewControllerが実行されなかった。
3画面以降は下記で囲うとかすれば動きそうだが、まあよろしくない実装なので、今回の方法を試してみるなど。

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
}

言い訳

今回一人でアプリ作ってるのもあり強制アンラップしたりしてるけど、よい子はまねしちゃいけないぞ。

おわり。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?