从导航控制器到选项卡控制器视图

Posted

技术标签:

【中文标题】从导航控制器到选项卡控制器视图【英文标题】:Going from Navigation controller to tab controller views 【发布时间】:2018-08-17 11:59:26 【问题描述】:

我正在开发 ios 应用程序。并且它有一些客户的设计限制。所以看起来我必须在不同数量的 Viewcontrollers 上同时使用导航控制器和选项卡控制器。

我可以将我的观点分为 2 类。

    注册/登录视图(这是应用首次启动时的入口点) MainView -> 一旦用户登录,这将成为入口点

现在类别 1 正在使用 NavigationView 控制器。其中 Category2 使用的是 Tab bar 控制器。

我想要的情况 1: 我想要当用户安装我的应用程序时,他会被带到具有导航视图的登录视图。现在,如果他还没有帐户,他将转到“创建新帐户”,这是导航视图的第二个场景。现在成功创建帐户后,他需要关闭所有其他导航视图控制器并需要跳转到将成为 Tabbar 视图控制器的 MainView。

案例2:假设用户在登录后关闭了我的应用程序,当他再次打开它时,现在的入口点将是具有标签栏视图控制器的Mainview。现在我知道我需要在 App 委托方法中执行此操作,但如何操作?

我正在这样做,它看起来像工作。但我没有得到底部标签。为什么会这样?

class ViewSwitcher 

    static func updateRootViewController() 

        let status = UserDefaults.standard.bool(forKey: KeyConstants.IS_USER_LOGGEDIN)
        var rootViewController : UIViewController?

        #if DEBUG
            print(status)
        #endif

        if (status == true) 
            let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
            let mainTabBarController = mainStoryBoard.instantiateViewController(withIdentifier: "idTab1VC") as! Tab1VC
            rootViewController = mainTabBarController
         else 
            let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
            let signInViewController = mainStoryBoard.instantiateViewController(withIdentifier: "idLoginVC") as! LoginVC
            rootViewController = signInViewController
        

        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.window?.rootViewController = rootViewController

    


知道如何处理这些情况吗?如何通过关闭所有视图控制器树以编程方式导航?

【问题讨论】:

您必须将某种标志或用户数据存储到任何永久存储中,例如 UserDefaults、SQLLite、CoreData 以识别用户已登录。然后您必须要求在 AppDelegate didFinishWithLaunchingOptions 中放置一个条件在窗口中设置应用程序 rootViewController。 告诉我如何设置应用程序 rootViewController。请告诉我这个 在 AppDelegateself.window.rootViewController = 中分配您的登录 navigationController 根目录,与 tabbarcontroller 相同。 @PratikSodha 请检查更新后的答案 @android teem Great.. 【参考方案1】:

我一直在为我的应用程序使用相同的过程。

使用此代码更改 Case2 中的 rootViewController

var window: UIWindow?
var tabBarController : UITabBarController?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 

        // Tabbar controller
        let storyBoard = UIStoryboard.init(name: "Main", bundle: Bundle.main)
        let tab1 = UINavigationController.init(rootViewController: storyBoard.instantiateViewController(withIdentifier: "tab1"))
        tab1 = UITabBarItem.init(title: "Title 1", image: UIImage(named : "Image.png") , tag: 0)
        let tab2 = UINavigationController.init(rootViewController: storyBoard.instantiateViewController(withIdentifier: "tab2"))
        tab2 = UITabBarItem.init(title: "Title 2", image: UIImage(named : "Image.png") , tag: 1)

        // Navigation controller or Login view controller
        let nav1 = UINavigationController.init(rootViewController: storyBoard.instantiateViewController(withIdentifier: "nav1"))

        tabBarController = UITabBarController.init()
        tabBarController?.delegate = self
        tabBarController?.selectedIndex = 0
        tabBarController?.viewControllers = [tab1,tab2]

       // The Bool value which you have to set as True after a user logged in 
        if UserDefaults.standard.bool(forKey: "LoggedIn")
            print("Tabbar")
            self.window?.rootViewController = self.tabBarController
        else
            print("Navigation")
            self.window?.rootViewController = nav1
        

        return true
    

在此之前或之后,您必须编写与用户在您的loginViewController 中单击登录相同的代码,在您的情况下是 Case1

     func loginClicked()
         UserDefaults.standard.set(true, forKey: "LoggedIn")
         DispatchQueue.main.async 
            let appdelegate = UIApplication.shared.delegate as! AppDelegate
            // Same as above code and replace self with appDelegate without if condition and at last
            appdelegate.window?.rootViewController = appdelegate.tabBarController
         
      

用户退出后

         DispatchQueue.main.async 
                    UserDefaults.standard.set(false, forKey: "LoggedIn")
                    let appdelegate = UIApplication.shared.delegate as! AppDelegate
                    let story = UIStoryboard.init(name: "Main", bundle: Bundle.main)
                    let nav1 = UINavigationController.init(rootViewController: storyBoard.instantiateViewController(withIdentifier: "nav1"))
                    appdelegate.window?.rootViewController = companyNavigation

【讨论】:

【参考方案2】:

在应用程序委托 didFinishWithLaunchingOptions 中使用以下代码,直接用于主视图。这里 uid 表示存储的值是否检查用户是否处于活动状态。

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                   if let user_id = UserDefaults.standard.value(forKey: "uid")
                   
                       let homeViewController = storyboard.instantiateViewController(withIdentifier: "HomeTabBarCtrlr") as! UITabBarController

                        let nav = UINavigationController(rootViewController: homeViewController)
                       self.window!.rootViewController = nav
                   else

注册/登录视图

【讨论】:

【参考方案3】:

逐步解决此问题的方法是:

    检查用户是否登录。为此使用 UserDefaults。 如果用户未登录,请将 LoginVC 设置为 rootVC。​​ 登录时在 UserDefault 中保存一个密钥以表示用户已登录。 下次用户打开应用时检查密钥,如果用户已登录,请将 TabBarVC 设置为 rootViewController。 在注销时,清除密钥。

上面的示例代码将是:

AppDelegate.swift

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
    
            ...........

        //Check for user login and set rootViewController.
        if UserDefaults.standard.bool(forKey: "login")
            self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
        
        else
            self.window?.rootViewController = UIStoryboard(name: "Login", bundle: nil).instantiateInitialViewController()
        
        return true
    

登录成功时

    func loginUser()
       ...
       if userLoginSuccess
        UserDefaults.standard.set(true, forKey: "login")
    

注销时

UserDefaults.standard.set(false, forKey: "login")

【讨论】:

【参考方案4】:

就像您知道您想在 Appdelgate 中执行此操作一样。

当用户登录成功时,您必须在 userdefault 中存储一个标志。 在应用程序委托中,您必须检查是否设置了此标志。如果已设置,则使用初始视图控制器调用 moveToLoginWindow() 创建导航视图控制器。 或者如果没有,则创建标签栏视图控制器调用 movetoTabBarController()

func moveToLoginWindow() -> Void 

        if let rootController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginVC") as? LoginVC
            let navigationController = UINavigationController.init(rootViewController: rootController)
            self.window?.rootViewController = navigationController
            self.window?.makeKeyAndVisible()
        
    


func movetoTabBarController() -> Void 

    let nav2 = UINavigationController()

    let second = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "secondViewController") as? SecureNotesVC
    nav2.viewControllers = [second!]
    nav2.tabBarItem =  UITabBarItem.init(title: "Titel 2", image: UIImage.init(named: "2.png"), selectedImage: UIImage.init(named: "2_sel.png"))


    let nav3 = UINavigationController()

    let third =  UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "thirdviewController") as? FormFillsVC
    nav3.viewControllers = [third!]
    nav3.tabBarItem = UITabBarItem.init(title: "Titel 2", image: UIImage.init(named: "3.png"), selectedImage: UIImage.init(named: "3_sel.png"))


    let nav4 = UINavigationController()

    let fourth = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "fourthviewContoller") as? SettingsVC
    nav4.viewControllers = [fourth!]
    nav4.tabBarItem =  UITabBarItem.init(title: "4", image: UIImage.init(named: "4.png"), selectedImage: UIImage.init(named: "4_sel.png"))




    if #available(iOS 11.0, *) 
        nav2.navigationBar.prefersLargeTitles = true
        nav3.navigationBar.prefersLargeTitles = true
        nav4.navigationBar.prefersLargeTitles = true
    

    let tabBarController = UITabBarController()
    tabBarController.viewControllers = [ nav2,nav3, nav4,nav5]
   self.window!.rootViewController = tabBarController;






 

【讨论】:

以上是关于从导航控制器到选项卡控制器视图的主要内容,如果未能解决你的问题,请参考以下文章

如何从导航控制器切换到选项卡控制器并使其成为根视图控制器

如何识别从UITabBarController中的更多选项卡或单独选项卡单击视图控制器?

单击隐藏选项卡视图控制器中的后退按钮时如何显示选项卡

在将导航控制器弹出回根视图的选项卡栏上检测到双击

将导航控制器添加到视图时无法传递数据

如何从 segue 中的另一个视图控制器实例化导航和选项卡控制器(显示详细信息)?