简体   繁体   中英

What's the right navigation structure for iOS Swift app with onboarding screens?

I'm creating an app that works as follows

  • Launch Screen
    • a. if "Getting Started" screens have been viewed and accepted then open main app
    • b. if not viewed/accepted then show "Getting started", then show main app once accepted

The "Getting Started" screens are quite self-contained so I've created a Storyboard for them, whereas the main app will be programatically created.

Where should the logic for (2) live? I was thinking about creating some sort of UINavigationController that would sit above both sets of screens and could decided what to show. Alternatively, I was going to just launch the main app VC and let the logic to show the "Getting Started" as a modal live there.

Any suggestions on best practise please?

use code launch in AppDelegate.h/SceneDelegate.h FYI,I believe you can still mix storyboard ViewController and code ViewController.However I suggest stick to only one style(in this case, code ViewController programmatically)

then use UserDefault to store whether user click "get started"

        // Set Root VC
    guard let windowScene = (scene as? UIWindowScene) else { return }
    window = UIWindow(frame: UIScreen.main.bounds)
    window?.windowScene = windowScene

    let navigator = Container.shared.resolve(INavigator.self)!
    let localStorageService = Container.shared.resolve(ILocalStorageService.self)!
    if localStorageService.isKeyExist(key: Configs.KEY_USER) {
        navigator.switchRoot(keyWindow: window!, scene: .main(viewModel: MainTabBarViewModel()))
    } else {
        navigator.switchRoot(keyWindow: window!, scene: .intro(viewModel: IntroViewModel()))
    }

There is no definitive answer. However, you may try to anticipate your needs a little bit:

  • if the onboarding screen is the only thing you will ever display this way, then you can put some code in the AppDelegate or in your main view controller,
  • if you plan to display this kind of screen after some releases (to present new features for example), you can use some kind of modal mechanism that can display a full screen modal that can be dismissed.

Regardless of the solution you choose:

Try to keep your code in an appropriate class or struct: the logic to decide what screen to show and how to create the view controller must be in an appropriate class or struct.This logic does not belong either in the AppDelegate nor in your home view controller — by the way, this is how you end with huge and messy view controllers.

For your need — choosing between several entities of the same kind — you can take a look at the factory design pattern . It is a common structure that encapsulates logic to create entities. You can design it to choose between your controllers:

class RootViewControllerFactory {

  var rootViewController: UIViewController {
    if shouldDisplayOnboardingScreen() {
      return generateOnboardingScreen()
    } else {
      return generateHomeScreen()
    }
  }

  private func shouldDisplayOnboardingScreen() -> Bool {
    // Your logic to decide whether you should display it or not.
  }

  func generateOnboardingScreen() -> UIViewController {
    // Load it from your storyboard
  }

  func generateHomeScreen() -> UIViewController {
    // Load it programmatically
  }

}

Then, your AppDelegate can use the proper view controller, but the code is not mixed up in the loading code. This makes reading much easier:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)

    self.window?.rootViewController = RootViewControllerFactory().rootViewController
    self.window?.makeKeyAndVisible()

    return true
}

With this solution, when the onboarding view controller is dismissed, you can call the generateHomeScreen() function of your factory to get the home screen and switch to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM