【问题标题】:Black screen after adding SceneDelegate and updating Info.plist添加 SceneDelegate 并更新 Info.plist 后黑屏
【发布时间】:2020-02-01 02:25:58
【问题描述】:

我目前正在使用 Xcode 11、Target iOS 13.0(该应用程序适用于所有低于 iOS 12.1 至 12.4 的版本)的空白屏幕,我想让我的应用程序同时适用于 12.1 以上的 iOS 用户和目前正在获得的 13.0尽管将以下 UIWindowSceneDelegate 添加到我现有的项目和 App Manifest 中,但仍出现空白屏幕:

添加应用清单文件

import UIKit
    import SwiftUI
    
    @available(iOS 13.0, *)
    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 user  = UserDefaults.standard.object(forKey: "defaultsuserid")
    
            let userSelfIdent  = UserDefaults.standard.object(forKey: "userinitialident")
            
            if let windowScene = scene as? UIWindowScene {
                
                let internalWindow = UIWindow(windowScene: windowScene)
                
                if (user != nil && userSelfIdent != nil){
                     let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                     let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
                        internalWindow.rootViewController = newViewcontroller
                        self.window = internalWindow
                        internalWindow.makeKeyAndVisible()
                }else {
                    
                    guard let _ = (scene as? UIWindowScene) else { return }
                }
            }
        }

以下是我的 AppDelegate,它首先被调用并执行 didFinishLaunchWithOptions 方法。我想知道只有当我的 Target ios 小于 13.0 并在 13.0 之后调用 SceneDelegate 方法来初始化我的 rootViewController 时,我才能调用此方法?

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    
    @available(iOS 13.0, *)
    func application(_ application: UIApplication,
                     configurationForConnecting connectingSceneSession: UISceneSession,
                     options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    @available(iOS 13.0, *)
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
      
    }
    


    @available(iOS 13.0, *)
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let _ = (scene as? UIWindowScene) else { return }
        
        if (user != nil && userSelfIdent != nil){

              let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
              let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
                self.window?.rootViewController = newViewcontroller
        }
    }
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        Thread.sleep(forTimeInterval: 3.0)
        
        UINavigationBar.appearance().barTintColor = UIColor(red:0.08, green:0.23, blue:0.62, alpha:1.0)
        
        if (user != nil && userSelfIdent != nil){

              let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
              let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
                self.window?.rootViewController = newViewcontroller
        }
        
        return true
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        let defaultUserID = UserDefaults.standard.string(forKey: "defaultUserID")
        
       
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        switch (application.applicationState) {
        case UIApplicationState.active:
            do something
           
        case UIApplicationState.background, UIApplicationState.inactive:
            
            let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let newViewcontroller = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
            self.window?.rootViewController = newViewcontroller            
        }
    }

【问题讨论】:

    标签: ios swift xcode appdelegate ios13


    【解决方案1】:

    我正在将一些示例代码从旧版 App Delegate 演示文稿移植到具有新 Scene Delegate 基础架构的新 Xcode 项目中。

    即使在将代码移动到场景代理之后,我还是会出现黑屏。

    问题在于我获取window 引用的方式。

    使用新的 UIWindow(windowScene:) 初始化器而不是 initWithFrame:

    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
        
        var window: UIWindow?
        
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            
            // OLD: causes black screen
            self.window = UIWindow(frame: UIScreen.main.bounds)
    
            // NEW: works perfectly
            guard let windowScene = (scene as? UIWindowScene) else { return }
            self.window = UIWindow(windowScene: windowScene)
            
            let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "INITAL_VIEW_CONTROLLER")
            self.window?.rootViewController = vc
            self.window?.makeKeyAndVisible()
        }
        
    }
    

    【讨论】:

      【解决方案2】:

      轻松按照以下步骤操作:

      1. 移除场景委托文件

      2. 将以下代码添加到 AppDelegate.swift

         class AppDelegate: UIResponder, UIApplicationDelegate {
        
         var window: UIWindow?
         func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
             return true
         }
        }
        
      3. 从 .plist 文件中删除 Application Scene Manifest 行

      【讨论】:

        【解决方案3】:

        使用 iOS 13 及更低版本运行的步骤:

        1. 将部署目标更改为 iOS 12。

        2. 将 AppDelegate 的方法替换为 iOS 12 开发应具备的方法。还要加上这个:

          var window: UIWindow?
          
        3. 删除 SceneDelegate。

        4. 删除 info.plist 中的应用程序场景清单。

        它适用于 iOS 13 和更低的 iOS 版本

        【讨论】:

        • 这一定是最好的答案!
        【解决方案4】:

        我在AppDelegate中注释了2个场景方法,然后就可以了 请检查我的截图

        【讨论】:

          【解决方案5】:

          xcode 11.6 @ionic/react 电容器应用程序

          更新时间:2020 年 7 月 22 日

          我们在 TestFlight 也遇到了黑屏问题。 我们终于解决了。

          检查 config.capacitor.json 看看你是否有本地主机, 删除服务器部分下的 URL.. 当我们运行发布时,我们(我)忘记了我们的 URL localhost 仍然存在,老实说,我不知道这可能是问题或从未想过要在那里检查, 我花了时间(几天)检查故事板建议。

          【讨论】:

            【解决方案6】:

            请参考上图并在 AppDelegate 中添加该行。

            【讨论】:

              【解决方案7】:

              当我遇到类似问题时,这是因为使用 Xcode 11.0 生成的单应用程序模板与使用 Xcode 11.2 构建的应用程序所需的模板不兼容。

              所以我刚刚使用 Xcode 11.2 创建了一个新的 Single-Page-App,并将生成的 SceneDelegate 复制到使用 Xcode 11.0 创建的旧项目中。

              在那之后,空白屏幕消失了,我的界面再次可见。

              【讨论】:

                【解决方案8】:

                我被这个问题困住了,最后我解决了从情节提要中删除 searchDisplayController 引用的问题。

                <searchDisplayController id="pWz-So-g6H">
                                    <connections>
                                        <outlet property="delegate" destination="Yci-sd-Mof" id="fjs-ah-jLs"/>
                                        <outlet property="searchContentsController" destination="Yci-sd-Mof" id="gQN-1r-gti"/>
                                        <outlet property="searchResultsDataSource" destination="Yci-sd-Mof" id="2Jf-lh-Ute"/>
                                        <outlet property="searchResultsDelegate" destination="Yci-sd-Mof" id="Hap-SA-f02"/>
                                    </connections>
                                </searchDisplayController>
                

                【讨论】:

                • 在使用 Xcode 13 为 iOS 13 构建应用程序后,我遇到了类似的问题。我的应用程序仅在 LaunchScreen 后显示黑屏。这仅在从 Testflight 安装时。在模拟器中或使用电缆(方案调试和发布)启动应用程序开始正常。还有 iOS 12:问题。正在做: 'grep -r -i 'searchDisplayController' 在 Main.storyboard 中显示了类似的文本。使用文本编辑器删除这些行并在 Xcode 13 中重新编译后,该应用程序现在可以在从 TestFlight 安装的 iOS 13 上正常启动!谢谢@Erick Martinez。
                • 我打开了 main.storyboard 的源代码,这个 searchDisplayController 已经不在了..
                【解决方案9】:

                这里有几个问题。请务必阅读与应用生命周期相关的文档,其中说明了在 iOS 13 下的调用以及在 iOS 12 下的调用。

                你可能还想看看我的支持 iOS 12 和 13 的Single View App template

                查看你的代码,这里是问题的总结:

                AppDelegate:

                • 如果应用在 iOS 12 或更早版本下运行,您应该只设置主窗口和根视图控制器。您需要在运行时检查这一点。
                • func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 方法不应在应用委托中。
                • 不直接相关,但在应用启动时从不休眠。删除 Thread.sleep(forTimeInterval: 3.0) 行。用户希望使用您的应用程序,而不是盯着启动屏幕超过必要的时间。在应用启动时阻塞主线程可能会导致您的应用被终止。

                场景代理:

                • 这基本没问题,但没有理由使用 guard let _ = (scene as? UIWindowScene) else { return } 行,尤其是因为它位于 if let 内,已经进行了检查。
                • 您似乎没有使用 SwiftUI,因此请删除该导入。

                我会将您的应用委托更新为更像这样:

                @UIApplicationMain
                class AppDelegate: UIResponder, UIApplicationDelegate {
                    var window: UIWindow?
                
                    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
                        UINavigationBar.appearance().barTintColor = UIColor(red:0.08, green:0.23, blue:0.62, alpha:1.0)
                
                        if #available(iOS 13.0, *) {
                            // In iOS 13 setup is done in SceneDelegate
                        } else {
                            let window = UIWindow(frame: UIScreen.main.bounds)
                            self.window = window
                
                            if (user != nil && userSelfIdent != nil){
                                let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                                let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
                                window.rootViewController = newViewcontroller
                            }
                        }
                
                        return true
                    }
                
                    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
                        if #available(iOS 13.0, *) {
                            // In iOS 13 setup is done in SceneDelegate
                        } else {
                            self.window?.makeKeyAndVisible()
                        }
                
                        return true
                    }
                
                    func applicationWillResignActive(_ application: UIApplication) {
                        // Not called under iOS 13 - See SceneDelegate sceneWillResignActive
                    }
                
                    func applicationDidEnterBackground(_ application: UIApplication) {
                        // Not called under iOS 13 - See SceneDelegate sceneDidEnterBackground
                    }
                
                    func applicationWillEnterForeground(_ application: UIApplication) {
                        // Not called under iOS 13 - See SceneDelegate sceneWillEnterForeground
                    }
                
                    func applicationDidBecomeActive(_ application: UIApplication) {
                        // Not called under iOS 13 - See SceneDelegate sceneDidBecomeActive
                    }
                
                    // 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.
                    }
                }
                

                您的场景委托可能是:

                @available(iOS 13.0, *)
                class SceneDelegate: UIResponder, UIWindowSceneDelegate {
                    var window: UIWindow?
                
                    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
                        guard let windowScene = (scene as? UIWindowScene) else { return }
                
                        let window = UIWindow(windowScene: windowScene)
                        self.window = window
                
                        if (user != nil && userSelfIdent != nil){
                            let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                            let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
                            window.rootViewController = newViewcontroller
                            window.makeKeyAndVisible()
                        }
                    }
                
                    func sceneDidDisconnect(_ scene: UIScene) {
                        // Called as the scene is being released by the system.
                    }
                
                    func sceneDidBecomeActive(_ scene: UIScene) {
                        // Not called under iOS 12 - See AppDelegate applicationDidBecomeActive
                    }
                
                    func sceneWillResignActive(_ scene: UIScene) {
                        // Not called under iOS 12 - See AppDelegate applicationWillResignActive
                    }
                
                    func sceneWillEnterForeground(_ scene: UIScene) {
                        // Not called under iOS 12 - See AppDelegate applicationWillEnterForeground
                    }
                
                    func sceneDidEnterBackground(_ scene: UIScene) {
                        // Not called under iOS 12 - See AppDelegate applicationDidEnterBackground
                    }
                }
                

                【讨论】:

                • 非常感谢 rmaddy。非常感谢您的时间和回答。不幸的是,在进行上述更改后,我仍然得到一个空白屏幕:(
                • 您的代码在运行时实际发生了什么?使用调试器逐步完成。从willConnectTo场景委托方法中的断点开始,一步一步走。它符合您的预期吗?
                • 什么都没有发生我在控制台中没有收到任何错误消息不确定发生了什么但我的模拟器变成空白...imgur.com/a/kip57Fg
                • 是否调用了willConnectTo?然后会发生什么?它是否达到了创建和设置根视图控制器的目的?再次,使用调试器单步执行代码。不要只依赖控制台输出。
                • 如果你把它搞砸了一次并且它已经安装在模拟器中,即使你的设置是正确的,每次新启动仍然是错误的......我终于通过删除应用程序并重新安装并解决了我的问题现在它终于再次起作用了。疯了。
                猜你喜欢
                • 1970-01-01
                • 2020-04-09
                • 2022-07-07
                • 1970-01-01
                • 2012-03-25
                • 2023-03-18
                • 1970-01-01
                • 2020-01-25
                • 1970-01-01
                相关资源
                最近更新 更多