iOS13 na Xcode 11 Czarny ekran nawet po dodaniu SceneDelegate i aktualizacji Info.plist


10

Obecnie otrzymuję pusty ekran z Xcode 11, docelowy iOS 13.0 (aplikacja działa dobrze ze wszystkimi poniższymi wersjami iOS 12.1 do 12.4), chcę, aby moja aplikacja działała zarówno dla użytkowników iOS powyżej 12.1, jak i 13.0 obecnie wyświetla pusty ekran pomimo dodając poniższy SceneDelegate do mojego istniejącego projektu i AppManifest

dodawanie pliku manifestu aplikacji

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

Oto moja AppDelegate, która jest wywoływana jako pierwsza i wykonuje didFinishLaunchWithOptionsmetodę. Chcę wiedzieć, jak mogę wywołać tę metodę tylko wtedy, gdy mój docelowy iOS jest mniejszy niż 13,0 i wywołać metodę SceneDelegate, aby zainicjować rootViewController po 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            
        }
    }

Odpowiedzi:


28

Masz tutaj kilka problemów. Ważne jest, aby przeczytać dokumentację związaną z cyklem życia aplikacji, która określa, co nazywa się pod iOS 13 i co nazywa się pod iOS 12.

Możesz także zobaczyć mój szablon aplikacji Single View, który obsługuje iOS 12 i 13.

Poniżej znajduje się podsumowanie problemów związanych z Twoim kodem:

AppDelegate:

  • Powinieneś skonfigurować główne okno i kontroler widoku głównego tylko wtedy, gdy aplikacja jest uruchomiona w systemie iOS 12 lub wcześniejszym. Musisz to sprawdzić w czasie wykonywania.
  • func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)Metoda nie powinna być w app delegata.
  • Nie bezpośrednio powiązane, ale nigdy nie śpij podczas uruchamiania aplikacji. Usuń Thread.sleep(forTimeInterval: 3.0)linię. Użytkownicy chcą korzystać z Twojej aplikacji, a nie patrzeć na ekran uruchamiania dłużej niż to konieczne. A zablokowanie głównego wątku podczas uruchamiania aplikacji może spowodować, że aplikacja zostanie zabita.

SceneDelegate:

  • Jest to w większości w porządku, ale nie ma powodu do guard let _ = (scene as? UIWindowScene) else { return }linii, zwłaszcza, że ​​jest w środku, if letktóry już to sprawdza.
  • Wygląda na to, że nie używasz SwiftUI, więc usuń ten import.

Zaktualizowałbym twojego delegata aplikacji, aby był mniej więcej taki:

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

Twój uczestnik sceny może wyglądać tak:

@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
Dziękuję bardzo rmaddy. Naprawdę doceniam twój czas i odpowiedź. Niestety po wprowadzeniu wyżej wymienionych zmian nadal pojawia się pusty ekran :(
Kris RaduhaSt

Co faktycznie dzieje się w twoim kodzie w czasie wykonywania? Przejdź przez debugger. Zacznij od punktu przerwania w willConnectTometodzie delegowania sceny i przejdź krok po kroku. Czy robi to, czego oczekujesz?
rmaddy

Nic się nie dzieje Nie otrzymuję żadnych komunikatów o błędach w konsoli, nie jestem pewien, co się dzieje, ale mój symulator jest pusty ... imgur.com/a/kip57Fg
Kris RaduhaSt

Się willConnectTonazywa? Co się wtedy stanie? Czy ma to sens tworzenia i ustawiania kontrolera widoku głównego? Ponownie przejdź przez kod za pomocą debugera. Nie polegaj tylko na wynikach konsoli.
rmaddy

Tak, to się nazywa i `window.rootViewController = newViewcontroller window.makeKeyAndVisible () 'to również zostało wykonane, ale widzę pusty ekran na symulatorze iOS 11-13.0, ale kiedy idę do Target i zmieniam na 12.1 zamiast 13.0, aplikacja działa dobrze.
Kris RaduhaSt

12

Więc kroki, aby dostać się do iOS 13 i niższej wersji

1) Zmień cel wdrażania na iOS 12.

2) Zastąp metody AppDelegate tym, co powinny mieć do opracowania iOS 12. Dodaj także:

   var window: UIWindow?

3) Usuń SceneDelegate.

4) Usuń manifest sceny aplikacji z listy info.plist.

Będzie działać zarówno na iOS 13, jak i niższej wersji iOS


To musi być najlepsza odpowiedź!
Swifty Codes

Najlepsza odpowiedź ....
Subrata Mondal

1

Utknąłem z tym problemem i wreszcie rozwiązałem usuwanie odwołań do searchDisplayController z scenorysu.

<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
Miałem podobny problem po zbudowaniu aplikacji na iOS 13 z Xcode 13. Moja aplikacja wyświetlała czarny ekran dopiero po uruchomieniu LaunchScreen. To tylko przy instalacji z Testflight. Uruchamianie aplikacji w symulatorze lub za pomocą kabla (schemat Debugowanie i wydanie) zaczynało się dobrze. Również iOS 12: problem w ogóle. Wykonanie: 'grep -r -i' searchDisplayController 'pokazał podobny tekst w Main.storyboard. Po usunięciu tych wierszy za pomocą edytora tekstu i ponownej kompilacji w Xcode 13 aplikacja działa teraz poprawnie na iOS 13 zainstalowanym z TestFlight! Dzięki @Erick Martinez.
Rodge

Otworzyłem źródło main.storyboard i nie ma tam tego searchDisplayController ..
timman

1

Kiedy miałem podobny problem, było to spowodowane tym, że szablon jednej aplikacji wygenerowany przy użyciu Xcode 11.0 był niezgodny z tym, który jest potrzebny dla aplikacji zbudowanej z Xcode 11.2.

Właśnie utworzyłem nową aplikację jednostronicową z Xcode 11.2 i skopiowałem wygenerowany SceneDelegate do mojego starego projektu, który został utworzony przy użyciu Xcode 11.0.

Potem zniknął pusty ekran i mój interfejs znów był widoczny.

Zróżnicowane


0

Z łatwością odłóż te kroki

1-) Usuń plik delegowania sceny

2-) Dodaj poniższy kod do AppDelegate.swift

    class AppDelegate: UIResponder, UIApplicationDelegate {

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

3) Usuń wiersz manifestu sceny aplikacji z pliku .plist wprowadź opis zdjęcia tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.