iOSのrootViewControllerを置き換える

# 目的
iOSではWindow配下にrootViewControllerがあり、これを入れ替えることによってメインのViewを変更することが可能ですが直接書き換えることは推奨されていません。
また、新規登録導線や既存ユーザーの導線など実現したい画面遷移はある程度決まっているので、定義しておくと楽です！


# 前提
ViewControllerの初期化でInstantiate、UIライブラリにMaterialを利用しているので、適時読み替えください
https://github.com/tarunon/Instantiate
https://github.com/CosmicMind/Material

# RootViewControllerの定義

早速ですが、RootViewController定義です。
ここではRootViewControllerのchildに呼び出したいUIViewControllerを配置し、アプリのどこからでも入れ替えできるようにします。
transitionToXXXではUIViewControllerを呼び出せればOK。

```swift:RootViewController.swift
final class RootViewController: UIViewController {
    private var current: UIViewController?

    init() {
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        addChildViewController()
    }

    func transition(to vc: UIViewController) {

        addChild(vc)
        vc.view.frame = view.bounds
        view.addSubview(vc.view)
        vc.didMove(toParent: self)
        current?.willMove(toParent: nil)
        current?.view.removeFromSuperview()
        current?.removeFromParent()
        current = vc
    }

    private func addChildViewController() {
        // ViewControllerをRootVCの子VCとして追加
        guard let current = current else {
            return
        }

        addChild(current)
        current.view.frame = view.bounds
        view.addSubview(current.view)
        current.didMove(toParent: self)
    }

    func transitionToHome() {
        let sidebarViewController = SidebarViewController.instantiate()
        let navigation = NavigationDrawerController(rootViewController: HomeViewController.instantiate(with: .init()), leftViewController: sidebarViewController)
        transition(to: navigation)
    }

    func transitionToEntrance() {
        let entranceViewController = EntranceViewController.instantiate()
        let navigation = UINavigationController(rootViewController: entranceViewController)

        transition(to: navigation)
    }

    func transitionToRegistar() {
        let entranceViewController = RegistarViewController.instantiate()
        let navigation = UINavigationController(rootViewController: entranceViewController)

        transition(to: navigation)
    }


}

```



# 画面遷移の呼び出し
AppDelegateでシングルトンにして、どこからでも呼び出せるようにしておきます
これで下記のように条件によっていい感じに画面を切り替えられるようになりました( ˙꒳​˙  )ｷﾘｯ

```swift:AppDelegate.swift
extension AppDelegate {

    static var shared: AppDelegate {
        UIApplication.shared.delegate as! AppDelegate
    }
    var rootViewController: RootViewController {
        window?.rootViewController as! RootViewController
    }
}
```

```swift:AppDelegate.swift
        let userData = UserDefaults.getUserData()
        if userData != nil {
            // メイン導線。ログインしている場合はここへ
            self.rootViewController.transitionToHome()
        } else if let currentUser = currentUser {
            //　firebase認証はしてるけどユーザー登録できてない時はここへ
            self.rootViewController.transitionToRegistar()
        } else {
            // 新規登録へ
            self.rootViewController.transitionToEntrance()
        }
```



参考
https://medium.com/@stasost/ios-root-controller-navigation-3625eedbbff