Swift 5添加SceneDelegate后根视图切换失效,登出功能异常
问题描述
添加SceneDelegate并迁移AppDelegate代码后,登出功能出现异常:点击登出按钮无即时反应,但关闭并重新打开应用后,用户会被正常登出。怀疑问题出在登出函数中使用的共享代理逻辑上。
相关代码
首页登出按钮代码
@IBAction func signOutButtonTapped(_ sender: Any) { KeychainWrapper.standard.removeObject(forKey: "accessToken") KeychainWrapper.standard.removeObject(forKey: "userID") // send user to splash page let signInPage = self.storyboard?.instantiateViewController(withIdentifier: "splashController") as! splashViewController let appDelegate = UIApplication.shared.delegate appDelegate?.window??.rootViewController = signInPage }
SceneDelegate.swift代码
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let _ = (scene as? UIWindowScene) else { return } let accessToken: String? = KeychainWrapper.standard.string(forKey: "accessToken") // If access token exists, skip login page if accessToken != nil { if let windowScene = scene as? UIWindowScene { self.window = UIWindow(windowScene: windowScene) let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil) let vc = mainStoryboard.instantiateViewController(withIdentifier: "homeTabController") as! TabBarController self.window!.rootViewController = vc } } } }
解决方案
问题核心:iOS 13+ 采用多场景架构后,AppDelegate不再负责窗口管理,实际窗口控制权已移交SceneDelegate。你当前的登出代码仍在尝试通过UIApplication.shared.delegate获取窗口,导致修改根控制器的操作无法作用到当前活跃窗口。
修复登出函数(单场景应用)
直接获取当前活跃场景的SceneDelegate,更新其窗口的根控制器:
@IBAction func signOutButtonTapped(_ sender: Any) { KeychainWrapper.standard.removeObject(forKey: "accessToken") KeychainWrapper.standard.removeObject(forKey: "userID") // 获取当前活跃场景的SceneDelegate及窗口 guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let sceneDelegate = windowScene.delegate as? SceneDelegate, let window = sceneDelegate.window else { return } // 跳转至启动页 let signInPage = self.storyboard?.instantiateViewController(withIdentifier: "splashController") as! splashViewController window.rootViewController = signInPage window.makeKeyAndVisible() // 确保窗口切换后可见 }
多场景支持优化(如iPad分屏)
如果应用支持多场景,遍历所有活跃场景并统一更新根控制器:
@IBAction func signOutButtonTapped(_ sender: Any) { KeychainWrapper.standard.removeObject(forKey: "accessToken") KeychainWrapper.standard.removeObject(forKey: "userID") let signInPage = self.storyboard?.instantiateViewController(withIdentifier: "splashController") as! splashViewController // 遍历所有活跃场景,统一切换登录页面 for scene in UIApplication.shared.connectedScenes { guard let windowScene = scene as? UIWindowScene, let sceneDelegate = windowScene.delegate as? SceneDelegate, let window = sceneDelegate.window else { continue } window.rootViewController = signInPage window.makeKeyAndVisible() } }
内容的提问来源于stack exchange,提问作者Two Chains
相关产品推荐
相关产品推荐

