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

додавання файлу програми 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метод. Я хочу знати, як я можу здійснити виклик цього методу лише у тому випадку, якщо мій ios Target менше 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, який підтримує 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
Дякую тобі дуже rmaddy. Дуже ціную ваш час та відповідь. На жаль, після внесення зазначених змін я все ще отримую порожній екран :(
Kris RaduhaSt

Що насправді відбувається у вашому коді під час виконання? Перейдіть за допомогою налагоджувача. Почніть з точки перерви в willConnectToметоді делегування сцени і перейдіть крок за кроком. Це робить те, що ви очікуєте?
rmaddy

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

Закликається willConnectTo? Тоді що відбувається? Чи стає точкою створення та встановлення контролера кореневого виду? Знову перегляньте код за допомогою налагоджувача. Не покладайтеся лише на вихід консолі.
rmaddy

Так, це називається і `window.rootViewController = newViewcontroller window.makeKeyAndVisible () 'це також виконується, але я бачу порожній екран на симуляторі iOS 11-13.0, але коли я переходжу до цільової та змінююсь на 12.1 замість 13,0, додаток працює чудово.
Kris RaduhaSt

12

Отже, кроки до переходу на версію iOS 13 та нижчої версії

1) Змініть ціль розгортання на iOS 12.

2) Замініть методи AppDelegate тим, що вони повинні мати для розробки iOS 12. Додайте також це:

   var window: UIWindow?

3) Видаліть SceneDelegate.

4) Видаліть маніфест сцени програми зі свого інформаційного списку.

Він буде працювати як на iOS 13, так і на нижній версії iOS


Це має бути найкращою відповіддю!
Швидкі коди

Найкраща відповідь ....
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
У мене була подібна проблема після створення програми для iOS 13 з Xcode 13. У мого додатку відображався лише чорний екран після LaunchScreen. Це лише при установці з Testflight. Запуск програми в тренажері або за допомогою кабелю (схема Налагодження та звільнення) починався нормально. Також iOS 12: випуск взагалі. Виконання: 'grep -r -i' searchDisplayController 'показав подібний текст у Main.storyboard. Після видалення цих рядків за допомогою текстового редактора та перекомпіляції в Xcode 13 додаток тепер запускається нормально на iOS 13, встановленому з TestFlight! Дякую @Erick Martinez
Rodge

я відкрив джерело для main.storyboard, і цей пошукDisplayController вже не там ..
timman

1

Коли у мене була подібна проблема, це було пов'язано з тим, що шаблон Single-App, згенерований за допомогою Xcode 11.0, був несумісний з тим, який потрібен додатку, побудованому за допомогою Xcode 11.2.

Тому я просто створив нову програму Single-Page з 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.