Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RootViewControllerで画面遷移をまとめた話

 RootViewControllerで画面遷移をまとめた話

煩雑になりがちな画面遷移をRootViewControllerクラスでまとめた話。

サンプルコード
https://github.com/SatoTakeshiX/RootViewController

参考サイト
iOSアプリを作るときのおすすめ構成 – Swift・iOSコラム – Medium
https://medium.com/swift-column/ios-2017-4f04d00a5804

iOS: Root Controller Navigation – Stan Ostrovskiy – Medium
https://medium.com/@stasost/ios-root-controller-navigation-3625eedbbff

AppRootControllerのご提案(簡略説明版)
https://speakerdeck.com/yimajo/approotcontrollerfalsegoti-an-jian-lue-shuo-ming-ban

iOS 9から追加された3D Touch shortcutsを実装してみる
https://qiita.com/koogawa/items/dd94a303c7852885f269

Sato Takeshi

April 03, 2018
Tweet

More Decks by Sato Takeshi

Other Decks in Programming

Transcript

  1. func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler

    completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { let naviCon = application.windows[0] .rootViewController as? UINavigationController RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 9
  2. //࠷ޙʹද͍ࣔͯͨ͠ը໘Λ൑அͯ͠ભҠΛ͢Δ //ද͍ࣔͯ͠ΔViewController͕ϝΠϯϏϡʔͳΒઃఆը໘ʹભҠɻ //͢Ͱʹઃఆը໘Λද͍ࣔͯ͠ΔͳΒɺίϯςφϏϡʔΛදࣔͤ͞Δɻ if let visibleMainViewCon = naviCon?.visibleViewController as? CallMainViewController

    { visibleMainViewCon.performSegue(withIdentifier: "gotoSettingFromPush", sender: true) } else if let visibleSettingViewCon = naviCon?.visibleViewController as? SettingViewController { // visibleSettingViewCon. visibleSettingViewCon.isFromPush.value = true visibleSettingViewCon.hiddenReplyViews(ishidden: !visibleSettingViewCon.isFromPush.value) } else if !(naviCon?.viewControllers.last is SettingViewController) { let popVC = naviCon?.popViewController(animated: true) print("ϙοϓͨ͠VC͸ \(type(of: popVC))") if let visibleSettingViewCon = naviCon?.visibleViewController as? SettingViewController { visibleSettingViewCon.isFromPush.value = true visibleSettingViewCon.hiddenReplyViews(ishidden: !visibleSettingViewCon.isFromPush.value) } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 10
  3. AppDelegate func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) ->

    Bool { setup() return true } private func setup() { window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = router.rootViewController window?.makeKeyAndVisible() } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 19
  4. private let _router = Router() extension AppDelegate { static var

    shared: AppDelegate { guard let delegate = UIApplication.shared.delegate as? AppDelegate else { fatalError("not set app delegate") } return delegate } var router: Router { return _router } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 20
  5. final class Router { enum Locate { case login case

    main case camera case setting } let rootViewController = RootViewController() func route(to locate: Locate, from viewController: UIViewController) { switch locate { case .login: rootViewController.showLoginScreen() break case .main: rootViewController.showMain() case .camera: rootViewController.showCameraScreen() break case .setting: rootViewController.showSettingScreen() break } } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 21
  6. class RootViewController: UIViewController { private var current: UIViewController init() {

    //ىಈ࣌͸ඞͣεϓϥογϡը໘Λදࣔ current = SplashViewController() super.init(nibName: nil, bundle: nil) } override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.blue addChildViewController(current) current.view.frame = view.bounds view.addSubview(current.view) current.didMove(toParentViewController: self) } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 22
  7. // RootViewController // MARK: ΞϓϦͰߦ͏۩ମతͳભҠ func showLoginScreen() { let new

    = LoginViewController.instantiate() addChildViewController(new) new.view.frame = view.bounds view.addSubview(new.view) new.didMove(toParentViewController: self) replaceCurrent(for: new) } func showMain() { switch current { case let tab as TabViewController: tab.selectMain() default: let tab = TabViewController.instantiate() animateFadeTransition(to: tab) } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 23
  8. Splashը໘ͷग़͠෼͚ func onViewDidload() { if UserDefaults.standard.bool(forKey: "IS_LOGIN") { //ϝΠϯը໘Λදࣔ AppDelegate.shared.router.route(to:

    .main, from: self) } else { UserDefaults.standard.set(true, forKey: "IS_LOGIN") //ϩάΠϯը໘Λදࣔ AppDelegate.shared.router.route(to: .login, from: self) } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 25
  9. struct DeepLinkShortcut { enum ItemType: String { case main case

    camera case setting } static func register() -> [UIApplicationShortcutItem] { let mainShortcutItem = UIApplicationShortcutItem(type: ItemType.main.rawValue, localizedTitle: "ϝΠϯը໘") let cameraShortcutItem = UIApplicationShortcutItem(type: ItemType.camera.rawValue, localizedTitle: "Χϝϥը໘") let settingShortcutItem = UIApplicationShortcutItem(type: ItemType.setting.rawValue, localizedTitle: "ઃఆը໘") return [mainShortcutItem, cameraShortcutItem, settingShortcutItem] } static func handleShortcut(_ shortcut: UIApplicationShortcutItem) -> ItemType? { return ItemType(rawValue: shortcut.type) } } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 27
  10. // AppDelegate private func setup() { window = UIWindow(frame: UIScreen.main.bounds)

    window?.rootViewController = router.rootViewController window?.makeKeyAndVisible() UIApplication.shared.shortcutItems = DeepLinkShortcut.register() } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 28
  11. // AppDelegate // MARK: Shortcuts func application(_ application: UIApplication, performActionFor

    shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { if let shortCut = DeepLinkShortcut.handleShortcut(shortcutItem) { let route = AppDelegate.shared.router switch shortCut { case .main: route.route(to: .main, from: route.rootViewController) case .camera: route.route(to: .camera, from: route.rootViewController) case .setting: route.route(to: .setting, from: route.rootViewController) } } completionHandler(true) } RootViewControllerͰը໘ભҠΛ·ͱΊͨ࿩ 29