最近教えて頂いたTipsなのですが、実際に使ってみて良かったので共有記事です。
皆さん、ログイン・ログアウトした時にメインのコンテンツとの画面切替ってどうやって実装されてますか?
調べてみて見かけるのはRootViewControllerを切り替える方法とかですかね、でもこの方法だとアニメーションが元々無いので自前で書かなくちゃいけなかったり、、、
そんな時に今回の主役UIPageViewController
の出番です!
特別難しい事はしていないので、コードを見てもらった方が分かりやすいと思います。
※ BasePageViewController
のStoryboard
を起動時のStoryboard
に設定しています。
BasePageViewController
import UIKit
extension Notification.Name {
static let pushToLogin = Notification.Name("PushToLogin")
static let pushToMainContents = Notification.Name("PushToMainContents")
}
class BasePageViewController: UIPageViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.pushTologin(_:)), name: .pushToLogin, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.pushToMainContents(_:)), name: .pushToMainContents, object: nil)
if ログインしているかの条件 {
pushToMainContents()
} else {
pushTologin()
}
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func pushTologin(_ notification: Notification? = nil) {
guard let login = login() else {
return
}
self.setViewControllers([login], direction: .forward, animated: true, completion: nil)
}
func pushToMainContents(_ notification: Notification? = nil) {
guard let mainContents = mainContents() else {
return
}
self.setViewControllers([mainContents], direction: .forward, animated: true, completion: nil)
}
private func login() -> UINavigationController? {
let loginStoryboard = UIStoryboard(name: "Login", bundle: nil)
guard let navigation = loginStoryboard.instantiateInitialViewController() as? UINavigationController else {
return nil
}
return navigation
}
private func mainContents() -> UINavigationController? {
let mainContentsStoryboard = UIStoryboard(name: "MainContents", bundle: nil)
guard let navigation = mainContentsStoryboard.instantiateInitialViewController() as? UINavigationController else {
return nil
}
return navigation
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
ログイン画面
import UIKit
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// ログイン完了 → メインコンテンツ画面へ
func pushToMainContents() {
NotificationCenter.default.post(name: .pushToMainContents, object: nil)
}
}
メインコンテンツ画面
import UIKit
class MainContentsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// ログアウト → ログイン画面へ
func pushToLogin(_ sender: UIButton) {
NotificationCenter.default.post(name: .pushToLogin, object: nil)
}
}
ViewController
を切り替える時にBasePageViewController
に対してNotification
を送っています。
使いどころとしては、Base
になっているViewController
を切り替えたい場合や起動時に任意の画面を開きたい(URLスキーム
、Local,Remote通知
からの起動等)時などに簡単にできるかと思います。
良かった点
-
UINavigationController
、UITabBarController
でもsetViewControllers
できるものだったら使用できる -
UIPageViewController
が持っているNavigationのPushの様な遷移を使って違和感なく遷移できる - 遷移先の画面に値を渡すこともできる(
Nofitication
のobject
やUserInfo
にセットしてPageViewController
で渡す)
イケてなかった点
-
ModalView
からの画面切り替えができない
※ 以下の様に閉じた後に処理をしないと動かない、起動時の画面遷移も同じなのでその場合はModal
を破棄してからでないと、、、
dismiss(animated: true, completion: {
NotificationCenter.default.post(name: .pushToLogin, object: nil)
})
UIPageViewController
の本来の使い方とは違いますが、自分は結構気に入っていて同じようなところで迷っている方の選択肢の一つになれたら幸いです。
最後に載せる程でもない簡単なサンプルはこちら → BasePageViewSample