iOS应用首次启动引导页设置问题排查及优化方案咨询
问题排查与优化方案
我想给App设置首次下载/重新下载时的引导页,需求是:首次启动显示instructionIntro页面,其余启动场景显示Main页面。目前这段代码写在GuideBookIntroClass里,但现在启动后还是会显示Main.storyboard里的旧引导页,求帮忙排查问题或给更优方案。
当前代码
let isFirstLaunch = UserDefaults.standard.value(forKey: "isFirstLaunch") as? Bool if isFirstLaunch == true { // 首次启动 let storyBoard : UIStoryboard = UIStoryboard(name: "instructionIntro", bundle:nil) let mainViewController = storyBoard.instantiateViewController(withIdentifier: "instructionIntro") as! InstructionIntroViewController let navigationController = UINavigationController(rootViewController: mainViewController) if let window = UIApplication.shared.delegate?.window { window?.rootViewController = navigationController } } else { // 非首次启动 let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) let mainViewController = storyBoard.instantiateViewController(withIdentifier: "Main") as! GuideBookIntroClass let navigationController = UINavigationController(rootViewController: mainViewController) if let window = UIApplication.shared.delegate?.window { window?.rootViewController = navigationController } }
问题排查点
- UserDefaults判断逻辑错误:首次启动时
isFirstLaunch是nil,nil == true结果为false,会直接走到else分支加载Main页面,完全搞反了首次启动的逻辑。 - 代码执行时机太晚:这段代码写在
GuideBookIntroClass里,说明App启动时已经先加载了Main.storyboard的页面,再执行这段切换代码,会导致先显示旧引导页再切换(甚至可能因为生命周期问题切换失败)。 - 未设置首次启动标记:即使逻辑正确,首次启动后没有把
isFirstLaunch设为true,下次启动还是会判定为首次启动。 - 控制器类型匹配问题:确认
Main.storyboard里标识符为Main的控制器,其类确实是GuideBookIntroClass,避免类型转换崩溃或错误。
优化解决方案
1. 修正UserDefaults逻辑并添加标记设置
把首次启动的判断改成检查isFirstLaunch是否为false,首次启动后立即设置标记:
// 首次启动判断:默认未标记则视为首次启动 let isFirstLaunch = UserDefaults.standard.bool(forKey: "isFirstLaunch") if !isFirstLaunch { // 首次启动:显示引导页 let storyboard = UIStoryboard(name: "instructionIntro", bundle: nil) let introVC = storyboard.instantiateViewController(withIdentifier: "instructionIntro") as! InstructionIntroViewController let navVC = UINavigationController(rootViewController: introVC) // 设置根控制器 if let window = UIApplication.shared.delegate?.window { window?.rootViewController = navVC } // 标记为已启动过 UserDefaults.standard.set(true, forKey: "isFirstLaunch") UserDefaults.standard.synchronize() } else { // 非首次启动:显示主页面 let storyboard = UIStoryboard(name: "Main", bundle: nil) let mainVC = storyboard.instantiateViewController(withIdentifier: "Main") as! GuideBookIntroClass let navVC = UINavigationController(rootViewController: mainVC) if let window = UIApplication.shared.delegate?.window { window?.rootViewController = navVC } }
2. 调整代码执行位置
把这段代码移到AppDelegate的application(_:didFinishLaunchingWithOptions:)方法里(iOS12及以下),或者SceneDelegate的scene(_:willConnectTo:options:)方法里(iOS13+),确保App启动初期就决定根控制器,避免先加载旧页面。
3. 额外检查项
- 确认
instructionIntro.storyboard的文件名和控制器标识符instructionIntro完全一致,控制器类是InstructionIntroViewController。 - 确认
Main.storyboard里的主控制器标识符为Main,类是GuideBookIntroClass。 - 如果用的是iOS13+的SceneDelegate,注意获取window的方式是从scene里获取:
// SceneDelegate里获取window的方式 guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = navVC self.window = window window.makeKeyAndVisible()
内容的提问来源于stack exchange,提问作者Parker
相关产品推荐
相关产品推荐

