即使添加了SceneDelegate并更新了Info.plist之后,Xcode 11黑屏上的iOS13


10

我目前正在使用Xcode 11,Target iOS 13.0进入黑屏状态(该应用程序在所有低于iOS 12.1至12.4的版本中均能正常工作),我想让我的应用程序可同时用于12.1以上的iOS用户和13.0的用户,尽管将以下SceneDelegate添加到我现有的项目中, AppManifest

添加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            
        }
    }

Answers:


28

您这里有几个问题。阅读与应用程序生命周期相关的文档非常重要,该文档阐明了iOS 13下的内容和iOS 12下的内容。

您可能还需要查看支持iOS 12和13的我的Single View App模板

查看您的代码,这是问题的摘要:

AppDelegate:

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

SceneDelegate:

  • 这通常很好,但是没有理由使用该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
    }
}

1
非常感谢您。真的很感谢您的时间和答复。不幸的是,在进行了上述更改之后,我仍然出现空白屏幕:(
Kris RaduhaSt '19

在运行时代码中实际发生了什么?逐步调试器。从willConnectTo场景委托方法中的断点开始,然后逐步进行。它能达到您的期望吗?
rmaddy19年

什么都没有发生我不确定控制台中没有任何错误消息,但不确定我的模拟器是什么... imgur.com/a/kip57Fg
Kris RaduhaSt

willConnectTo称为?那会怎样 它是否可以创建和设置根视图控制器?同样,使用调试器逐步执行代码。不要仅仅依靠控制台输出。
-rmaddy

是的,它被称为“ window.rootViewController = newViewcontroller window.makeKeyAndVisible()”,它也会执行,但是我在iOS 11-13.0模拟器上看到一个空白屏幕,但是当我转到Target并更改为12.1而不是13.0时,App运行正常。
克里斯·拉杜哈

12

因此,升级到iOS 13及更低版本的步骤

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

2)将AppDelegate的方法替换为iOS 12开发应具有的方法。还要添加以下内容:

   var window: UIWindow?

3)删除SceneDelegate。

4)在info.plist中删除Application Scene Manifest。

它可以在iOS 13和更低的iOS版本上运行


这必须是最好的答案!
Swifty代码

最佳答案....
Subrata Mondal

1

我陷入了这个问题,最后我解决了从情节提要中删除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>

2
使用Xcode 13构建适用于iOS 13的应用程序后,我遇到了类似的问题。我的应用程序在LaunchScreen之后仅显示黑屏。仅当从Testflight安装时才这样做。在模拟器中或使用电缆(方案“调试和发布”)启动应用程序运行正常。也是iOS 12:根本没有问题。这样做:'grep -r -i'searchDisplayController'在Main.storyboard中显示了类似的文本。在使用文本编辑器删除了这些行并在Xcode 13中重新编译之后,该应用程序现在可以在从TestFlight安装的iOS 13上正常运行了!谢谢@Erick Martinez。
罗杰

我打开源main.storyboard这searchDisplayController不再有..
蒂曼

1

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

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

之后,黑屏消失了,我的界面再次可见。

差异


0

轻松享受这些步骤

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行 在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.