应用程序启动时的View协调器:我应该使用View Controller还是其他工具?

时间:2019-03-19 17:32:36

标签: ios swift

目前,我的应用主界面如下:

enter image description here

Root View Controller 本身没有任何值,需要确定要显示哪个控制器。逻辑相当复杂,但这对这个问题并不重要。最简单的类似示例如下所示:

override func viewDidAppear(_ animated: Bool) {

        var controller: UIViewController?

        if !userIsAuthenticated {
            let storyboard = UIStoryboard(name: "Login", bundle: nil)
            controller = storyboard.instantiateViewController(withIdentifier: "loginController")

        }
        else if systemHasAlert {
            let storyboard = UIStoryboard(name: "Alert", bundle: nil)
            controller = storyboard.instantiateViewController(withIdentifier: "alertController")
        }
        else {
            let storyboard = UIStoryboard(name: "Landing", bundle: nil)
            controller = storyboard.instantiateViewController(withIdentifier: "defaultLandingPage")
        }

        guard let _controller = controller else {
            return 
        }

        navigationController?.pushViewController(_controller, animated: true )
}

(逻辑本身是象征性的,不是那么简单。但这足以传达这个想法。)

该控制器还为应用程序状态更改提供了一个稳定的“返回点”。例如,在用户成功登录后,我要做的就是:

AppDelegate.shared.navigationController?.popToRootViewController(animated: false)

这将导致重新评估 Root View Controller 中的条件,并且应用程序导航到另一个视图

通常这可以,但是我不喜欢3件事:

  1. 此“根”视图暂时可见,这种中断使从一个视图平滑过渡到另一个视图。我试图通过将viewDidAppear替换为viewWillAppear来解决此问题,但在那种情况下,导航似乎根本没有发生
  2. 此视图在技术上是不需要的
  3. 从概念上讲,视图控制器充当其他视图的协调者似乎不正确。

那么有没有更好的选择来提供这样的“根级别”协调器?还是根视图协调器是正确的选择,我应该担心正确地设置样式,而不是消除它?

预先感谢

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解正确,但是似乎根本不需要根视图控制器,但需要显示三个控制器之一(即“登录”,“警告”和“着陆”)。

在这种情况下,确实似乎视图控制器中的viewDidAppear方法不是处理此逻辑的最佳位置。最简单的方法是在AppDelegate方法中的application(_:didFinishLaunchingWithOptions:)类内处理逻辑。您的实现可能如下所示:


var window: UIWindow?

...

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Initialize navigation controller without root view controller
    let navigationVC = UINavigationController()


    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    // Set navigationVC as a root view controller in your application
    // Now it would ignore your storyboard.
    window?.rootViewController = navigationVC

    var controller: UIViewController?

    if !userIsAuthenticated {
        let storyboard = UIStoryboard(name: "Login", bundle: nil)
        controller = storyboard.instantiateViewController(withIdentifier: "loginController")

    }
    else if systemHasAlert {
        let storyboard = UIStoryboard(name: "Alert", bundle: nil)
        controller = storyboard.instantiateViewController(withIdentifier: "alertController")
    }
    else {
        let storyboard = UIStoryboard(name: "Landing", bundle: nil)
        controller = storyboard.instantiateViewController(withIdentifier: "defaultLandingPage")
    }

    if let controller = controller {
        navigationVC.pushViewController(controller, animated: false)
    }

    return true
}

P.S。:请记住,上述实现会覆盖情节提要文件中定义的应用程序的入口点。

P.P.S::您在原始帖子中提到了“协调员”。上面显示的方法是最简单的方法,但可能不是最好的方法。对于更复杂的逻辑,您可能确实需要实现协调器。尽管许多iOS开发人员都熟悉协调器概念,但在iOS社区中没有唯一的实现方法。因此,我将只讨论讨论协调器的几个链接,希望对您有所帮助:

  1. http://khanlou.com/2015/10/coordinators-redux/
  2. http://khanlou.com/2017/05/back-buttons-and-coordinators/
  3. http://merowing.info/2016/01/improve-your-ios-architecture-with-flowcontrollers/
  4. https://hackernoon.com/coordinators-routers-and-back-buttons-c58b021b32a
  5. https://talk.objc.io/episodes/S01E5-connecting-view-controllers