最初打开 iOS13+ 应用程序后更新/更改根视图控制器

Posted

技术标签:

【中文标题】最初打开 iOS13+ 应用程序后更新/更改根视图控制器【英文标题】:Updating/Changing root view controller after initially opening app for iOS13+ 【发布时间】:2020-02-21 10:49:29 【问题描述】:

我正在尝试将根视图控制器从 ViewController() 更新为 fourYearPlan()。当用户最初打开应用程序时,他们会在ViewController() 中受到欢迎并引导至TableViewController()。从那里,当他们点击 tableViewCell 时,它将引导他们到 fourYearPlan() 并自动将根视图控制器更改为它。如果用户按下fourYearPlan() 中的按钮,根视图控制器将重置为ViewController()。我将如何解决这个问题?

AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate 

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
        // Override point for customization after application launch.
        updateRootVC()
        return true
    

    // MARK: UISceneSession Lifecycle

    @available(ios 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration 
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    

    @available(iOS 13.0, *)
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) 
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    

    func updateRootVC()

        let status = UserDefaults.standard.bool(forKey: "status")

        print(status)

        if status == true 
            let navController = UINavigationController(rootViewController: fourYearPlan())
            window?.rootViewController = navController
        
        else
            let navController = UINavigationController(rootViewController: ViewController())
            window?.rootViewController = navController
        
        window?.makeKeyAndVisible()
    

SceneDelegate 部分:

class SceneDelegate: UIResponder, UIWindowSceneDelegate 

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).  
        guard let _ = (scene as? UIWindowScene) else  return 
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.window = window
        appDelegate.updateRootVC()

    

ViewController() 将导致TableViewController(),如果单击,fourYearPlan 将成为 ViewController() 的新根视图控制器:

     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

        tableView.deselectRow(at: indexPath, animated: true)

        let layout = UICollectionViewFlowLayout()
        let destination = fourYearPlan(collectionViewLayout: layout)

//        UserDefaults.standard.set(true, forKey: "status")
//        let appDelegate = UIApplication.shared.delegate as! AppDelegate
//        appDelegate.updateRootVC()


        navigationController?.pushViewController(destination, animated: true)

    

fourYearPlan() 中用于重置根视图控制器的按钮:

    @objc func addTapped(sender: UIBarButtonItem!) 
        let addAlert = UIAlertController(title: "Start Over", message: "Are you sure you want to create a new plan?", preferredStyle: .alert)


        addAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler:  (action:UIAlertAction) in
            let defaults = UserDefaults.standard

//            defaults.set(false, forKey: "status")
//            let appDelegate = UIApplication.shared.delegate as! AppDelegate
//            appDelegate.updateRootVC()

            let domain = Bundle.main.bundleIdentifier!
            defaults.removePersistentDomain(forName: domain)
            defaults.synchronize()


            let destination = ViewController()
            self.navigationController?.pushViewController(destination, animated: true)

        ))

        addAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

        self.present(addAlert, animated: true, completion: nil)
    

【问题讨论】:

我不明白。在fourYearPlan() 中按下按钮时,您想移动到ViewController() 还是rootViewController? 您已经在使用导航控制器“推送”到fourYearPlan ... 为什么不直接返回pop?或者,如果您要从viewController()tableViewController()fourYearPlan,并且您想跳过表格视图并直接返回第一个视图,您可以使用popToRootViewController()popToViewController()(并指定要弹出的目标)。 @PGDev 在fourYearPlan 中按下按钮,我想让ViewController() 成为新的rootviewcontroller。当用户第一次打开应用程序时,他们会看到 viewcontroller() 作为 rootviewcontroller,然后转换到 tableviewcontroller(),在其中他们单击一个单元格转到fourYearPlan() 并将新的 rootviewcontroller 作为fourYearPlan()。 @DonMag ViewController()TableViewController() 有点像登录屏幕。我希望用户在首次安装和打开应用程序时收到ViewController()TableViewController() 的问候。之后,我希望fourYearPlan() 成为初始根视图控制器。 【参考方案1】:

适用于 Xcode 13+、Swift 5+

打开 SceneDelegate 并粘贴替换它,将 CustomerMainViewController 替换为您的视图控制器

   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else  return 

        if UserDefaultHelper.isLoggedIn! 
            print("User logged in")
            let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) // this assumes your storyboard is titled "Main.storyboard"
            let yourVC = mainStoryboard.instantiateViewController(withIdentifier: "CustomerMainViewController") as! CustomerMainViewController // inside "YOUR_VC_IDENTIFIER" substitute the Storyboard ID you created in step 2 for the view controller you want to open here. And substitute YourViewController with the name of your view controller, like, for example, ViewController2.
            self.window?.rootViewController = yourVC
            self.window?.makeKeyAndVisible()
        
        else 
            print("User Not logged in")
        
        
    

【讨论】:

以上是关于最初打开 iOS13+ 应用程序后更新/更改根视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

当被模态视图控制器覆盖时,iOS 6 视图控制器布局在方向更改后不会更新

在运行时更改 iOS 13 中的根视图控制器

更改 iOS 窗口的根视图控制器

iOS10 Facebook 登录弹出到根视图控制器

动态设置拆分视图控制器为根视图控制器IOS

在 AppDelegate 中动画后不显示根视图控制器