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

SwiftUI迁移UIKit后无SceneDelegate调用黑屏,求替代私有API方案

问题场景

从SwiftUI应用重构为UIKit应用后,曾安装过旧版SwiftUI应用的设备升级新版UIKit应用时出现黑屏。排查发现:

  • SceneDelegate的所有方法均未被调用
  • AppDelegate中的application(_:configurationForConnecting:options:)方法未触发
  • 删除旧版后重新安装新版则无问题,推测是iOS 13+的Scene会话缓存机制导致,但无法要求用户手动删除旧版。

目前仅能通过私有API临时解决,但无法用于正式版本:

application.openSessions.forEach { session in
    application.perform(Selector(("_removeSessionFromSessionSet:")), with: session)
}
替代私有API的可行方案

1. 强制返回UIKit场景配置,忽略缓存

在AppDelegate的场景配置方法中,直接返回指定的UIKit场景配置,不依赖系统缓存的旧配置:

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // 强制生成UIKit场景配置,覆盖缓存的旧SwiftUI配置
    let sceneConfig = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    sceneConfig.delegateClass = SceneDelegate.self
    // 如果使用Storyboard,指定对应的Storyboard文件
    sceneConfig.storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
    return sceneConfig
}

原理:系统缓存的旧会话可能关联了SwiftUI的场景配置,此方法强制为所有连接的会话分配新的UIKit配置,绕过缓存。

2. 清理Info.plist中的冗余场景配置

确保UIApplicationSceneManifest配置仅保留UIKit相关项,删除旧的SwiftUI配置:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Default Configuration</string>
                <key>UISceneDelegateClassName</key>
                <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                <key>UISceneStoryboardFile</key>
                <string>Main</string>
            </dict>
        </array>
    </dict>
</dict>

原理:移除旧配置后,系统无法找到缓存会话对应的配置,会自动使用新的UIKit配置初始化场景。

3. 异步销毁旧会话并重建新场景

在didFinishLaunchingWithOptions中异步销毁所有缓存的旧会话,然后手动创建新的UIKit场景:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    guard !application.openSessions.isEmpty else { return true }
    
    for session in application.openSessions {
        application.requestSceneSessionDestruction(session, options: nil) { [weak self] _ in
            guard let self = self else { return }
            // 销毁旧会话后,创建新的UIKit场景
            let newConfig = UISceneConfiguration(name: "Default Configuration", sessionRole: .application)
            newConfig.delegateClass = SceneDelegate.self
            application.requestSceneSessionCreation(configuration: newConfig, options: nil)
        }
    }
    return true
}

注意:此方法依赖异步回调,需确保场景创建的时机正确,避免重复创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:38:11