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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/58207755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:02:45  来源:igfitidea点击:

iOS13 on Xcode 11 Black screen even after adding SceneDelegate and updating Info.plist

iosswiftxcodeappdelegateios13

提问by Kris RaduhaSt

I am currently getting a blank screen with Xcode 11, Target iOS 13.0 (the app works fine with all below versions iOS 12.1 till 12.4), I want to make my App work for both iOS users above 12.1 and also 13.0 currently getting blank screen despite adding the below SceneDelegate to my existing project and AppManifest

我目前正在使用 Xcode 11 获得空白屏幕,目标 iOS 13.0(该应用程序适用于所有低于 iOS 12.1 到 12.4 的版本),我想让我的应用程序同时适用于 12.1 和 13.0 以上的 iOS 用户,尽管目前仍然获得空白屏幕将下面的 SceneDelegate 添加到我现有的项目和 应用程序清单

adding App Manifest file

添加应用程序清单文件

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

The following is my AppDelegate which is getting called first and executing the didFinishLaunchWithOptionsmethod. I want to know how can i make this method call only if my Target ios is less than 13.0 and call SceneDelegate method to initialize my rootViewController after 13.0?

以下是我的 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            
        }
    }

回答by rmaddy

You have several issues here. It's important to read the documentation related to the app lifecycle which states what is called under iOS 13 and what is called under iOS 12.

你在这里有几个问题。阅读与应用程序生命周期相关的文档很重要,其中说明了在 iOS 13 下调用的内容和在 iOS 12 下调用的内容。

You may also want to see my Single View App templatethat supports iOS 12 and 13.

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

Looking at your code, here is a summary of the problems:

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

AppDelegate:

应用委托:

  • You should only setup the main window and the root view controller if the app is being run under iOS 12 or earlier. You need to check this at runtime.
  • The func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)method should not be in the app delegate.
  • Not directly related but never sleep on app startup. Remove the Thread.sleep(forTimeInterval: 3.0)line. Users want to use your app, not stare at the launch screen longer than necessary. And blocking the main thread on app launch can cause your app to be killed.
  • 如果应用程序在 iOS 12 或更早版本下运行,您应该只设置主窗口和根视图控制器。您需要在运行时检查这一点。
  • func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)方法不应在应用程序委托中。
  • 没有直接关系,但在应用程序启动时从不休眠。删除Thread.sleep(forTimeInterval: 3.0)线。用户希望使用您的应用程序,而不是盯着启动屏幕的时间过长。在应用程序启动时阻塞主线程可能会导致您的应用程序被终止。

SceneDelegate:

场景委托:

  • This is mostly fine but there is no reason for the guard let _ = (scene as? UIWindowScene) else { return }line, especially since it is inside an if letthat already does that check.
  • You don't appear to be using SwiftUI so remove that import.
  • 这基本上没问题,但没有理由进行该guard let _ = (scene as? UIWindowScene) else { return }行,特别是因为它在if let已经进行该检查的内部。
  • 您似乎没有使用 SwiftUI,因此请删除该导入。

I would update your app delegate to be more like this:

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

@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.
    }
}

Your scene delegate could be like:

你的场景委托可能是这样的:

@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
    }
}

回答by Vinayak Bhor

So steps to getting to an iOS 13 and lower version

所以升级到 iOS 13 及更低版本的步骤

1) Change deployment target to iOS 12.

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

2) Replace the AppDelegate's methods with what they ought to have for iOS 12 development. Also add this:

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

   var window: UIWindow?

3) Remove SceneDelegate.

3) 删除SceneDelegate。

4) Remove Application Scene Manifest in your info.plist.

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

It will work on both iOS 13 and lower iOS Version

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

回答by Emre Gürses

Easly fallow these steps

轻松休养这些步骤

1-) Remove scene delegate file

1-) 删除场景委托文件

2-) Add below code to AppDelegate.swift

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

    class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        return true
    }
   }

3-) Remove the Application Scene Manifest line from your .plist file enter image description here

3-) 从 .plist 文件中删除 Application Scene Manifest 行 在此处输入图片说明

回答by Erick Martinez

I was stuck with this problem, and finally i solved removing the searchDisplayController references from storyboard.

我被这个问题困住了,最后我解决了从故事板中删除 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>

回答by appleitung

When I had a similar issue it was due to the Single-App template generated using Xcode 11.0 was incompatible to the one being needed for an app built with Xcode 11.2.

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

So I just created a new Single-Page-App with Xcode 11.2 and copied the generated SceneDelegate to my old project which was created using Xcode 11.0.

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

After that, the blank screen was gone an my interface visible once more.

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

Diff

差异