You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift在SceneDelegate切换window.rootViewController出现黑屏闪屏问题

iOS 15下SceneDelegate切换rootViewController黑屏闪屏问题解决

问题概述

在SceneDelegate中切换window.rootViewController时出现毫秒级黑屏闪屏,显示流程为:启动页→瞬间黑屏→正常窗口,已尝试多种常规方案仍未解决,怀疑与iOS 15特性或操作遗漏有关。

已尝试无效方案

  • 用DispatchQueue.main.async {}包裹切换逻辑
  • 提前设置Dummy ViewController作为过渡载体
  • 给目标ViewController的view设置backgroundColor = .white

针对性解决方案

1. 确保Window背景色与启动页一致

切换rootViewController时,若window本身未设置背景色,会短暂显示系统默认的黑色。在初始化window时直接设置与启动页匹配的背景色:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)
    // 设置为启动页的背景色,比如白色或启动页主题色
    window.backgroundColor = .white
    self.window = window
    window.makeKeyAndVisible()
}

2. 使用UIWindow的setRootViewController(_:options:)方法(iOS 13+)

直接赋值rootViewController可能触发系统隐式过渡逻辑,改用带选项的API更可控,即使设置0时长动画也能避免黑屏:

let targetVC = YourTargetViewController()
// 无动画切换,避免突兀视觉变化
window?.setRootViewController(targetVC, options: UIWindow.TransitionOptions(
    animationCurve: .linear,
    duration: 0.0
))

3. 延迟切换至App激活后执行

避免在scene(_:willConnectTo:options:)中立即切换,等App完全激活(sceneDidBecomeActive回调)后再处理,此时window状态更稳定:

private var hasConfiguredRootVC = false

func sceneDidBecomeActive(_ scene: UIScene) {
    guard !hasConfiguredRootVC, let window = window else { return }
    hasConfiguredRootVC = true
    
    let targetVC = YourTargetViewController()
    targetVC.view.backgroundColor = window.backgroundColor
    window.rootViewController = targetVC
}

4. 排查多Window冲突

检查App中是否存在未正确隐藏的其他window,确保只有主window处于key且visible状态,多余window会干扰显示层级。

示例完整代码

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    private var hasSetRootVC = false

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        // 匹配启动页背景色
        window.backgroundColor = .white
        self.window = window
        window.makeKeyAndVisible()
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        guard !hasSetRootVC, let window = window else { return }
        hasSetRootVC = true
        
        let targetVC = HomeViewController()
        targetVC.view.backgroundColor = window.backgroundColor
        
        window.setRootViewController(targetVC, options: UIWindow.TransitionOptions(
            animationCurve: .linear,
            duration: 0.0
        ))
    }
}

内容的提问来源于stack exchange,提问作者husharoonie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:35:28