如何通过以编程方式将根(选项卡 ViewController)从子选项卡设置为未实例化的不同 VC

Posted

技术标签:

【中文标题】如何通过以编程方式将根(选项卡 ViewController)从子选项卡设置为未实例化的不同 VC【英文标题】:How to unwind through progrmmatically set rootVC (tabViewController) from child tab to different VC that was not instantiated 【发布时间】:2020-07-11 18:00:21 【问题描述】:

Swift 5 / xCode 11.5

当应用启动时,App Delegate 将检查用户手机上保存的身份验证令牌。如果它不存在,它将显示什么是 InitialViewController(实例化它,将其设置为 rootViewController,并在窗口中显示它)。如果存在令牌,它将实例化并将 MainTabController 设置为 rootVC 并显示它。层次结构如下所示:

RegisterViewController (之间没有导航控制器)InitialViewController LoginViewController 如果成功登录或注册,上述所有控制器都会推送到 MainTabController,假设手机上不存在用户的身份验证令牌(这些“视图之间没有导航控制器” ',只是推送/关闭。)。MainTabController 具有三个选项卡,它们是通过 NavControllers 连接的 UIViewControllers。

由于 rootVC 是在 AppDelegate 中以编程方式通过 Window 对象实例化和显示的,因此 InitialViewController 无法从 MainTabController 上的选项卡(已设置作为 rootVC),假设用户确实有一个保存的身份验证令牌。

我的解决方法是删除身份验证令牌,然后在 AppDelegate 中调用一个函数,该函数将切换 rootViewController 并让 Window 显示它(返回到 InitialViewController)。我担心所有其他被实例化的 VC,这可能会导致内存堆积。当我这样做时,是否所有 MainTabController 的 子级都被解除分配?这是注销操作和切换 rootVC 的代码:

退出

@IBAction func logout(_ sender: Any) 
        
        UserServices.logoutUser() 
            responseResult in
            if responseResult == .Success 
                CommonUtils.clearAuthToken()
                CommonUtils.clearAllUserDefaultData()
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                appDelegate.switchRootViewController()
             else 
                self.showAlert(title: "Error", message: responseResult.rawValue)
            
        

AppDelegate 中的 switchRootViewController

func switchRootViewController() -> Void 
        let rootController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "InitialViewController")
        self.window?.rootViewController = rootController
    

我已经用 unwind segue 尝试过(内部注销操作)

        let initialController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "InitialViewController")
        initialController.addChild(self) // self is tab VC I'm trying to unwind from
        let children = initialController.children

        self.performSegue(withIdentifier: "unwindToHomeScreen", sender: self)

InitialViewControllers 展开 segue 代码

    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool 
        return true
    

    override func canPerformUnwindSegueAction(_ action: Selector, from fromViewController: UIViewController, sender: Any?) -> Bool 
        return true
    

    @IBAction func unwindToInitialViewController(sender: UIStoryboardSegue) 

我认为这种展开不起作用,因为 InitialViewController 不存在引用。我会显示布局图片,但在产品发布之前,该项目本质上是秘密的......如果您需要更多信息或者我在问题描述中不清楚,请告诉我。

【问题讨论】:

【参考方案1】:

如果你试试这个:

func ToSomeScreen() 
    
    let homeViewController = storyboard?.instantiateViewController(identifier: "Storyboard ID") as? ScreenCustummerViewController  //file name for next screen
    
    view.window?.rootViewController = homeViewController
    view.window?.makeKeyAndVisible()
    

【讨论】:

我当前用于切换 rootVC 的实现是有效的,我只是问我是否会造成内存泄漏,因为 MainTabController 的所有子代都没有被破坏。文档还说makeKeyAndVisible() 窗口将: > 将其放置在同一级别或更低级别的所有其他窗口的前面,我需要将它们全部解除或取消分配。或者通过 MainTabController 找到一些放松的方法。

以上是关于如何通过以编程方式将根(选项卡 ViewController)从子选项卡设置为未实例化的不同 VC的主要内容,如果未能解决你的问题,请参考以下文章

Vb.net 如何以编程方式选择选项卡控件中的最后一个选项卡

如何以编程方式更改初始标签栏选择

如何以编程方式打开视图控制器的某些选项卡

如何以编程方式切换到 UITabBarController 中的另一个选项卡?

如何以编程方式更改 Vuetify 选项卡和 vue-router

ExtJs:在非活动选项卡中以编程方式选择 GridPanel 的行不起作用?