Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Black screen after adding SceneDelegate and updating Info.plist

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                     }     } 
like image 923
Kris RaduhaSt Avatar asked Oct 02 '19 18:10

Kris RaduhaSt


People also ask

Why is there a black screen when I open an app?

app on your Android mobile device, this is likely due to an incompatibility issue with Android System Webview. This issue may occur immediately upon opening the application, when trying to sign in, or when creating a new account. To resolve this issue: Open the Google Play Store.

What is SceneDelegate in Swift?

AppDelegate is responsible for handling application-level events, like app launch and the SceneDelegate is responsible for scene lifecycle events like scene creation, destruction and state restoration of a UISceneSession.

How do I add launch screen to Xcode 13?

If your project doesn't contain a default launch screen file, add a launch screen file and set the launch screen file for the target in the project editor. Choose File > New > File. Under User Interface, select Launch Screen, and click Next.


2 Answers

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     } } 
like image 161
rmaddy Avatar answered Oct 03 '22 20:10

rmaddy


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

like image 20
Vinayak Bhor Avatar answered Oct 03 '22 19:10

Vinayak Bhor