应用程序启动时的视图协调器:我应该使用视图控制器还是其他东西?

Posted

技术标签:

【中文标题】应用程序启动时的视图协调器:我应该使用视图控制器还是其他东西?【英文标题】:View coordinator on application startup: should I use View Controller or something else? 【发布时间】:2019-03-19 17:32:36 【问题描述】:

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

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

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 件事:

    此根视图暂时可见,这会破坏从一个视图到另一个视图的平滑过渡。我试图通过用viewWillAppear 替换viewDidAppear 来解决它,但在这种情况下似乎根本没有发生导航 技术上不需要此视图 在概念层面上,视图控制器充当其他视图的协调器似乎是不对的。

那么有没有更好的选择来提供这样的“根级”协调器?还是根视图协调器是正确的选择,我宁愿担心正确地对其进行样式化,而不是消除它?

提前致谢

【问题讨论】:

【参考方案1】:

我不确定我是否理解正确,但您似乎根本不需要根视图控制器,但您需要显示三个控制器之一(即“登录”、“警报”和“ Landing") 应用程序启动时。

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


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 社区中没有单一的实现方法。因此,我将仅放置几个讨论协调器的链接,希望对您有用:

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

【讨论】:

是的,协调器的想法正在流传……甚至我的实现也是一个这样的教程的变体。不幸的是,由于几个原因,我不能使用您的建议。两个重要的是:首先,我还想在应用程序状态更改时重用相同的逻辑,正如我在登录用户的示例中所解释的那样。您提供的第一个链接中提到了另一个重要原因:“Overstuffed App Delegates”是我想避免的。不过还是感谢您的回复! 您可以将AppDelegate 中定义的逻辑放在AppCoordinator 中,它将处理其他协调器(即“LoginCoordinator”、“LandingCoordinator”等)并跟踪应用程序状态的变化。但是,您将需要初始化AppCordinator,我认为除了 AppDelegate 之外没有比这更好的地方了。您可能会将这种情况视为“应用程序代理过多”,但我认为在这种情况下,AppDelegate 内部的逻辑将非常少。

以上是关于应用程序启动时的视图协调器:我应该使用视图控制器还是其他东西?的主要内容,如果未能解决你的问题,请参考以下文章

应用程序在应用程序启动错误结束时应该有一个根视图控制器 [重复]

IOS:使用 url 方案从浏览器启动应用程序时加载视图控制器?

我在应用程序加载而不是图像时开发启动视频。并且​​还使用 ios 中的推送视图控制器导航到下一页

错误:应用程序在应用程序启动结束时应该有一个根视图控制器

“应用程序窗口应该在应用程序启动结束时有一个根视图控制器”在我禁用情节提要后发生

使用多个视图控制器时的可达性检查