添加 SceneDelegate 并更新后黑屏 Info.plist

Black screen after adding SceneDelegate and updating Info.plist

我目前在 Xcode 11、Target iOS 13.0 时出现空白屏幕(该应用程序在所有以下版本 iOS 12.1 至 12.4 下运行良好),我想制作尽管将以下 UIWindowSceneDelegate 添加到我现有的项目和 App Manifest,但我的应用程序同时适用于 12.1 和 13.0 以上的 iOS 用户当前出现黑屏:

正在添加应用清单文件

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 13 下的调用以及 iOS 12.

下的调用

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

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

AppDelegate:

  • 如果应用程序 运行 在 iOS 12 或更早版本下,您应该只设置主 window 和根视图控制器。您需要在 运行 时间检查此内容。
  • 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
    }
}

我被这个问题困住了,最后我解决了从故事板中删除 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 11.0 生成的单应用程序模板与使用 Xcode 11.2 构建的应用程序所需的模板不兼容。

所以我刚刚使用 Xcode 11.2 创建了一个新的单页应用程序,并将生成的 SceneDelegate 复制到我使用 Xcode 11.0 创建的旧项目中。

之后,黑屏消失了,我的界面又出现了。

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

  1. 将部署目标更改为 iOS12.

  2. 将 AppDelegate 的方法替换为 iOS 12 开发应有的方法。还要添加:

    var window: UIWindow?
    
  3. 删除 SceneDelegate。

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

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

轻松执行以下步骤:

  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 文件中删除应用程序场景清单行

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

xcode 11.6 @ionic/react 电容应用

更新时间:2020 年 7 月 22 日

我们在 TestFlight 也有黑屏问题。 WE终于解决了。

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

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

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

即使在将代码移动到 Scene Delegate 之后,我仍然遇到黑屏。

问题是我获取对 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()
    }
    
}