iOS13 на Xcode 11 Черный экран даже после добавления SceneDelegate и обновления Info.plist


10

В настоящее время я получаю пустой экран с Xcode 11, Target iOS 13.0 (приложение прекрасно работает со всеми нижеприведенными версиями iOS 12.1 до 12.4), я хочу, чтобы мое приложение работало как для пользователей iOS выше 12.1, так и для 13.0, в настоящее время получающих пустой экран, несмотря на добавив ниже SceneDelegate в мой существующий проект и AppManifest

добавление файла манифеста приложения

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метод. Я хочу знать, как я могу сделать этот вызов метода, только если мой целевой показатель ниже 13.0 и вызвать метод SceneDelegate для инициализации моего rootViewController после 13.0?

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

Ответы:


28

У вас есть несколько вопросов здесь. Важно прочитать документацию, относящуюся к жизненному циклу приложения, в которой говорится, что называется в iOS 13 и что называется в iOS 12.

Вы также можете захотеть увидеть шаблон моего приложения Single View App, который поддерживает iOS 12 и 13.

Глядя на ваш код, вот краткое изложение проблем:

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

Что на самом деле происходит в вашем коде во время выполнения? Перейдите к отладчику. Начните с точки останова в willConnectToметоде делегата сцены и идите шаг за шагом. Это делает то, что вы ожидаете?
rmaddy

Ничего не происходит, я не получаю никаких сообщений об ошибках в консоли, не уверен, что происходит, но мой симулятор гаснет ... imgur.com/a/kip57Fg
Kris RaduhaSt

Является ли willConnectToназывается? Тогда что происходит? Получает ли смысл создавать и настраивать контроллер корневого представления? Опять пошагово код с помощью отладчика. Не просто полагаться на вывод консоли.
rmaddy

Да, это называется, и `window.rootViewController = newViewcontroller window.makeKeyAndVisible () 'также выполняется, но я вижу пустой экран на симуляторе iOS 11-13.0, но когда я перехожу к Target и изменяю на 12.1 вместо 13.0, приложение работает нормально.
Kris RaduhaSt

12

Итак, шаги по переходу на iOS 13 и ниже

1) Измените цель развертывания на iOS 12.

2) Замените методы AppDelegate на то, что они должны иметь для разработки под iOS 12. Также добавьте это:

   var window: UIWindow?

3) Удалить SceneDelegate.

4) Удалите манифест сцены приложения в вашем info.plist.

Он будет работать как на iOS 13, так и ниже.


Это должен быть лучший ответ!
Swifty Codes

Лучший ответ ....
Субрата Мондал

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
У меня была похожая проблема после создания приложения для iOS 13 с Xcode 13. Мое приложение показывало только черный экран после LaunchScreen. Это только при установке из Testflight. Запуск приложения в симуляторе или с помощью кабеля (схема Debug and Release) запускался нормально. Также iOS 12: проблема вообще. Выполнение: 'grep -r -i' searchDisplayController 'показывал похожий текст в Main.storyboard. После удаления этих строк с помощью текстового редактора и перекомпиляции в Xcode 13 приложение теперь нормально запускается на iOS 13, установленной из TestFlight! Спасибо @ Эрик Мартинес.
Rodge

Я открыл исходный код для main.storyboard, и этот searchDisplayController больше не существует ..
Тимман

1

Когда у меня возникла похожая проблема, это было связано с тем, что шаблон Single-App, созданный с помощью Xcode 11.0, был несовместим с тем, который был необходим для приложения, созданного с Xcode 11.2.

Поэтому я просто создал новое одностраничное приложение с Xcode 11.2 и скопировал сгенерированный 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 введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.