34

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 UIWindowSceneDelegate to my existing project and App Manifest:

AppManifest

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 didFinishLaunchWithOptions method. 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?

@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            
        }
    }
pkamb
  • 33,281
  • 23
  • 160
  • 191
Kris RaduhaSt
  • 509
  • 1
  • 5
  • 13

10 Answers10

47

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.

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

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.

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 let that already does that check.
  • You don't appear to be using SwiftUI so remove that import.

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
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 5
    Thank you so much rmaddy. Really appreciate your time and answer. Unfortunately, after making the aforementioned changes i still get a blank screen :( – Kris RaduhaSt Oct 02 '19 at 22:20
  • What actually happens in your code at runtime? Step through with the debugger. Start with a breakpoint in the `willConnectTo` scene delegate method and go step by step. Does it do what you expect? – rmaddy Oct 02 '19 at 22:25
  • Nothing happens i don't get any error messages in the console not sure what's going on but my simulator goes blank... https://imgur.com/a/kip57Fg – Kris RaduhaSt Oct 02 '19 at 22:39
  • Is `willConnectTo` called? Then what happens? Does it get t the point of creating and setting the root view controller? Again, step through the code with the debugger. Don't just rely on console output. – rmaddy Oct 03 '19 at 01:02
  • Yes it is called and `window.rootViewController = newViewcontroller window.makeKeyAndVisible()' this also executed but i see a blank screen on iOS 11-13.0 simulator but when i go to Target and change to 12.1 instead of 13.0 the App works fine. – Kris RaduhaSt Oct 03 '19 at 01:19
  • When you use iOS 11 or iOS 12, it doesn't use the scene delegate at all. Try changing the window's background color to something obvious in the SceneDelegate willConnectTo. Is it still black? Try just creating and using a plain view controller to rule out a problem with your storyboard. – rmaddy Oct 03 '19 at 01:46
  • Update: I just changed my Simulator to iPhone 11 ProMax - 13.0 and i see the window color changed to RED as mentioned in my SceneDelegate ' let window = UIWindow(windowScene: windowScene) window.backgroundColor = UIColor.red self.window = window' surprisingly my initialViewController is not getting called after splash screen. – Kris RaduhaSt Oct 03 '19 at 03:04
  • Based on your debugging, is the line to set the root view controller being reached? You do have that `if` statement. Perhaps it's false and not set the view controller. – rmaddy Oct 03 '19 at 03:56
  • Yes rmaddy it is reached, i tried removing the if also and it is yet blank.... If the `if` line fails it should go back and show initialViewController and that is showing blank as well... – Kris RaduhaSt Oct 03 '19 at 14:55
  • Something wrong with my Storyboard but lastly i got it working. Thank you very much, your help is immensely appreciated and you helped pushing a whole family ahead :) – Kris RaduhaSt Oct 03 '19 at 17:16
  • Hi Kris, did you resolve this issue, i am stuck with the same problem, and i think the problem is the SWRevealViewController class, because i change that in the rootViewController for other ViewController and its work fine. and i am using the target 13.1. Maybe the problem is from XCode, in this issue https://github.com/John-Lluch/SWRevealViewController/issues/816 XaviXO mentioned that the class doesn´t work with Xcode 11. In this moment i am downloading the Xcode 11.2 Beta 2 – Erick Martinez Oct 25 '19 at 02:41
  • 9
    If you messed this up once and it's already installed in the simulator, every new launch will still be wrong even if your settings are correct... I finally solved my issue by removing the App and reinstalling and now it finally works again. Crazy. – Bob de Graaf May 14 '21 at 10:58
  • @BobdeGraaf you should post that as an answer, because that’s ultimately what fixed this for me. Silly fix, but it’s a fix! – stanlemon Jun 20 '22 at 20:14
  • @stanlemon Good idea! I just added it as an answer :) – Bob de Graaf Jun 22 '22 at 09:44
  • Removing App from simulator and running it again from XCode reaaly solves this issue! How the richest company in the world allowed to release product with so stupid bugs??? – Юрий Сталоверов Mar 06 '23 at 21:30
36

Steps for running with iOS 13 and lower versions:

  1. Change deployment target to iOS 12.

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

    var window: UIWindow?
    
  3. Remove SceneDelegate.

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

It will work on both iOS 13 and lower iOS Version

pkamb
  • 33,281
  • 23
  • 160
  • 191
Vinayak Bhor
  • 691
  • 1
  • 8
  • 20
10

Easily follow these steps:

  1. Remove scene delegate file

  2. Add below code to 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

    Remove Scene Manifest

pkamb
  • 33,281
  • 23
  • 160
  • 191
Emre Gürses
  • 1,992
  • 1
  • 23
  • 28
4

The accepted answer is correct in a lot of ways, but I believe it's not a complete answer. I posted a comment that already helped several people to fully solve the issue, so I will post this as an answer as well:

If you messed this up once and it's already installed in the simulator, every new launch will still have this issue, even if your settings are correct...

The solution is to remove the App and reinstall it with the corrected code! It's a crazy fix, but it works!

Bob de Graaf
  • 2,630
  • 1
  • 25
  • 43
  • 1
    Ha, thank you friend, this was my issue. I was pulling my hair out trying to see what I misconfigured, but in the end it was just the simulator in a bad state. Deleting the app from the springboard and re-building fixed me up! – David Zorychta Feb 18 '23 at 00:53
2

I commented 2 scene methods in the AppDelegate, and then it works please check my screenshot enter image description here

Peter Nguyen
  • 61
  • 1
  • 3
1

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

<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>
Erick Martinez
  • 283
  • 4
  • 7
  • 2
    I had a similar issue after building the app for iOS 13 with Xcode 13. My app was only showing a black screen after the LaunchScreen. This only when installing from Testflight. Starting the app in the simulator or with a cable (scheme Debug and Release) was starting fine. Also iOS 12: issue at all. Doing: 'grep -r -i 'searchDisplayController' showed similar text in Main.storyboard . After removing these lines with a text-editor and recompiling in Xcode 13, the app now starts fine on iOS 13 installed from TestFlight! Thanks @Erick Martinez. – Rodge Nov 02 '19 at 20:06
  • i opened the source for main.storyboard and this searchDisplayController is no longer in there.. – timman Apr 03 '20 at 23:39
1

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.

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.

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

Diff

appleitung
  • 1,043
  • 7
  • 10
1

Please refre nabove image

Please refer above image and add the line in AppDelegate.

Sheetal Shinde
  • 489
  • 5
  • 7
0

xcode 11.6 @ionic/react capacitor app

UPDATED:7/22/2020

We had black screen issue at TestFlight too. WE finally solved.

Check config.capacitor.json and see if u have localhost there, delete URLs under server section.. we(I) forgot our URL localhost still there when we run release, to be honest i did not know that could be problem or never think to check there, I spent time(days) to check storyBoard suggestions.

greenridinghood
  • 629
  • 5
  • 7
0

I was porting some sample code from older App Delegate presentation to a new Xcode project with the new Scene Delegate infrastructure.

Even after moving the code the Scene Delegate, I was getting a black screen.

The issue was the way in which I was getting a reference to the window.

Use the new UIWindow(windowScene:) initializer rather than initWithFrame:.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    var window: UIWindow?
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        // OLD: causes black screen
        self.window = UIWindow(frame: UIScreen.main.bounds)

        // NEW: works perfectly
        guard let windowScene = (scene as? UIWindowScene) else { return }
        self.window = UIWindow(windowScene: windowScene)
        
        let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "INITAL_VIEW_CONTROLLER")
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()
    }
    
}
pkamb
  • 33,281
  • 23
  • 160
  • 191