Help us understand the problem. What is going on with this article?

RootViewの切り替えにUIPageViewControllerが使いやすかった話

More than 3 years have passed since last update.

最近教えて頂いたTipsなのですが、実際に使ってみて良かったので共有記事です。

皆さん、ログイン・ログアウトした時にメインのコンテンツとの画面切替ってどうやって実装されてますか?

調べてみて見かけるのはRootViewControllerを切り替える方法とかですかね、でもこの方法だとアニメーションが元々無いので自前で書かなくちゃいけなかったり、、、

そんな時に今回の主役UIPageViewControllerの出番です!

特別難しい事はしていないので、コードを見てもらった方が分かりやすいと思います。
BasePageViewControllerStoryboardを起動時の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を送っています。

PageViews.gif

使いどころとしては、BaseになっているViewControllerを切り替えたい場合や起動時に任意の画面を開きたい(URLスキームLocal,Remote通知からの起動等)時などに簡単にできるかと思います。

良かった点

  • UINavigationControllerUITabBarControllerでもsetViewControllersできるものだったら使用できる
  • UIPageViewControllerが持っているNavigationのPushの様な遷移を使って違和感なく遷移できる
  • 遷移先の画面に値を渡すこともできる(NofiticationobjectUserInfoにセットしてPageViewControllerで渡す)

イケてなかった点

  • ModalViewからの画面切り替えができない
    ※ 以下の様に閉じた後に処理をしないと動かない、起動時の画面遷移も同じなのでその場合はModalを破棄してからでないと、、、
dismiss(animated: true, completion: {
    NotificationCenter.default.post(name: .pushToLogin, object: nil)
})

UIPageViewControllerの本来の使い方とは違いますが、自分は結構気に入っていて同じようなところで迷っている方の選択肢の一つになれたら幸いです。

最後に載せる程でもない簡単なサンプルはこちら → BasePageViewSample

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした