【Swift】画面を全て閉じて、ホーム画面に戻る
どうも、ねこきち(@nekokichi1_yos2)です。
今開いている画面を全て閉じて、ホーム画面(もしくは初期画面)へ1発で戻りたい場合があります。
かといって、
- dismissを多用する → 処理の流れが複雑に
- ホーム画面に遷移する → 画面が生成され、処理が圧迫される
の問題点が。
そこで、生成された画面を全て閉じて、最初の画面(ホーム画面)に戻る方法を書いていきます。
解説
方法は
- RootViewController
- presentingViewController
- unWindSegue
を使った3つです。
RootViewController
RootViewControllerはアプリ画面の初期画面(アプリ起動時、最初に表示されるViewController ) 。
RootViewControllerでdismissを発動させると、RootViewController以降に開かれた画面(生成されたViewController)を全て削除する。
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
結果、1番最初の画面に戻れる。
ドキュメントによると、
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack.
複数のビューコントローラーを連続して提示し、提示されたビューコントローラーのスタックを構築する場合、スタックの下位にあるビューコントローラーでこのメソッドを呼び出すと、その直接の子ビューコントローラーと、スタック上のその子より上のすべてのビューコントローラーが閉じます。
引用:Appleドキュメントより
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss
なので、親であるRootViewControllerより上の、子であるViewController達を削除するってことかな?
presentingViewController
開いている画面を指定して、直接閉じる方法。
self.presentingViewController?.dismiss(animated: true, completion: nil)
注意点として、rootViewController(アプリ起動時の画面)から1つの画面が開かれている場合、
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
と指定しないと、RootViewControllerには戻れない。
もし1つだけだと、現在表示している画面しか閉じない。
なので、
- 現在の画面とRootViewControllerの間にある画面の数 + 1
を指定した方がいい。
unWindSegue
Segueを利用した方法。
@IBAction func unwindSegue(for unwindSegue: UIStoryboardSegue, towards subsequentVC: UIViewController) {}
手順は、
- 1番最初の画面(ホーム画面)に上記のメソッドを記述
- StoryBoardで処理を実行したいUI(例:UIButton)をcontrolキーを押下しながらExitと紐づける
- 1番最初の画面で定義したメソッドを選択
(★ここ重要)unWindSegueは、unWindSegueのメソッドを定義した画面に戻るので、もしホーム画面に戻るなら、ホーム画面に記述する。
(2:UIとExitの紐付け)
(3:戻り先で定義したunWindSegueのメソッドを選択)
結果
StoryBoard
(CloseAll - 4つ目の画面 - ButtonはExitでunWindSegueのメソッドと紐付け)
dismissの場合
unwindSegueの場合
ソースコード
rootViewController(最初の画面)
import UIKit class rootViewController: UIViewController { @IBAction func unwindSegue(for unwindSegue: UIStoryboardSegue, towards subsequentVC: UIViewController) { } }
closeAll(4つ目の画面)
import UIKit class CloseAll: UIViewController { @IBAction func closeAllViewController(_ sender: Any) { self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) self.presentingViewController?.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil) } }
参考