When creating a new iOS project in Xcode 12 a UISceneDelegate is added automatically. Since my App should be available on iOS 11+ (which does not support UISceneDelegate) I had to remove it.
Removing the UISceneDelegate from info.plist and from the AppDelegate was no problem of course. However I wonder if I have to add any code to application(_: didFinishLaunchingWithOptions) In most tutorial I found this method is simply left empty, only var window: UIWindow? had to be added. Other sources show that some setup code has to be added.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
/* Manual Setup */
// let window = UIWindow(frame: UIScreen.main.bounds)
// window.rootViewController = ViewController() // Your initial view controller.
// window.makeKeyAndVisible()
// self.window = window
return true
}
}
In my tests everything works fine without any additional setup code. The rootViewController is loaded automatically from Storyboard and everything works fine.
Is this just coincident, is this some Xcode magic happening in the background (adding rootVC automatically if code is missing), or is my code (without setup) broken and will eventually fail at some very bad moment
You only need to make sure
1- UISceneDelegate is deleted
2- Key UIApplicationSceneManifest is removed from Info.plist
3- These methods are removed from AppDelegate
// MARK: UISceneSession Lifecycle
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)
}
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.
}
4- Add var window: UIWindow? to AppDelegate
5- Make sure entry point vc is selected in Main.storyboard
After that Don't worry of anything and leave didFinishLaunchingWithOptions empty as if there is no change happened in Xcode 11
This question already has answers here:
Opt out of UISceneDelegate/SwiftUI on iOS
(6 answers)
Closed 3 years ago.
I just started a new project of iOS. I created the project using xcode 11 and iOS 13. When I created project i found out that in order to set our own rootController we have to use sceneDelegate instead of AppDelegate. I want to ask if there is any possibility to use old method of setting rootControllers in AppDelegate instead of using sceneDelegate.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let loginController: HomeViewController = HomeViewController(nibName: "HomeViewController", bundle: nil)
// let navController: UINavigationController = UINavigationController(rootViewController: loginController)
self.window?.rootViewController = loginController
self.window?.makeKeyAndVisible()
// Override point for customization after application launch.
return true
}
}
Follow these steps to use AppDelegate and opt-out for SceneDelegate
Go to Info.plist and remove Application Scene Manifest entry from Info.plist.
Remove SceneDelegate.swift
Add var window: UIWindow? in your AppDelegate.swift file
Delete the UISceneSession Lifecycle code from AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let mainStoryBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
let loginController = mainStoryBoard.instantiateViewController(withIdentifier: "HomeViewController")
self.window?.rootViewController = loginController
self.window?.makeKeyAndVisible()
return true
}
}
Make sure to give "HomeViewController" storyboardID to your view controller.
This is how your AppDelegate.swift file should look now. You are good to go!
Why don't you use the SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
//Make sure to do this else you won't get
//the windowScene object using UIApplication.shared.connectedScenes
self.window?.windowScene = windowScene
let storyBoard: UIStoryboard = UIStoryboard(name: storyBoardName, bundle: nil)
window?.rootViewController = storyBoard.instantiateInitialViewController()
window?.makeKeyAndVisible()
}
If you don't want to use sceneDelegate then you can remove all sceneDelegate and also remove 'Application Scene Manifest' from info.plist
set UIWindow variable
var window: UIWindow?
Make sure you have removed Application Scene Manifest this from info.plist and change the background colour of your view controller.
Your device's Dark Mode is enable if you want to remove dark mode from app add this key into your info.plist
User Interface Style = Light
My console posted this error today, [ApplicationLifecycle] UIWindows were created prior to initial application activation. This may result in incorrect visual appearance.
This has caused Application UI to not behave properly. I have never seen this before and need some insight on where to start debugging.
macOS: Catalina 10.15
XCode version: Version 11.1
I think that apps main UIWindow should be lazily initiated. Try with this:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window?.rootViewController = RootViewController() // root view controller
window?.makeKeyAndVisible()
return true
}
}
I have just developed an app, but when running in the simulator the debugger console says:
The app delegate must implement the window property if it wants to use
a main storyboard file.
I have an app delegate file. What does the message mean, and how can I get my app working?
Make sure you have the following property declaration in your AppDelegate class:
var window: UIWindow?
If you run your project on earlier than iOS 13.0, in that case you will face the problem. Because of iOS 13 and later, app launch differently than earlier versions.
In iOS 13 and later, use UISceneDelegate objects to respond to life-cycle events in a scene-based app
In iOS 12 and earlier, use the UIApplicationDelegate object to respond to life-cycle events.
When you launch the app in iOS 12 and earlier then UIApplicationMain class expect a window property in your AppDelegate class as like SceneDelegate has. So your problem will be solved if you add the following line in your AppDelegate class.
var window: UIWindow?
For Objective-C
#property (strong, nonatomic) UIWindow *window;
You can find more here App's Life Cycle.
Just in case anyone comes across this again and is programming in Objective-C make sure you have this line of code in your AppDelegate.h file:
#property (strong, nonatomic) UIWindow *window;
I have received this error, when I created new project in XCode 11. I have not used SwiftUI. Here are the steps, I have considered to fix this.
Deleted Application Scene Manifest entry from Info.plist
Deleted SceneDelegate.swift file
Deleted all scene related methods in AppDelegate.swift class
added var window: UIWindow? property in AppDelegate.swift class
After these steps, I am able to run the app on version prior to iOS 13.
[EDIT]
Finally, your AppDelegate.swift file should look something like the following.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
Add the following window declaration in Appdelegate file
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window:UIWindow?
...
Implementation of this property is required if your app’s Info.plist file contains the UIMainStoryboardFile key.
The default value of this synthesized property is nil, which causes the app to create a generic UIWindow object and assign it to the property. If you want to provide a custom window for your app, you must implement the getter method of this property and use it to create and return your custom window.
I had the same issue, just add var window: UIWindow? as the debug error says.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
You can check your app delegate class:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// 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.
}
}
Error: The app delegate must implement the window property if it wants to use a main storyboard file
Swift 5 & Xcode 11
Make sure that SceneDelegate contains UIWindow property
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
//...
}
Setting in Info.plist
Application Scene Manifest > Enable Mutliple Windows > false.
This solved the problem for me.
Long ago answered, but to help understand the questions above about why simply adding the window property solves the problem, note that the app delegate conforms to the UIApplicationDelegate protocol which defines a property, #property (nullable, nonatomic, strong) UIWindow *window; that classes need to provide to specify the window to use when presenting a storyboard. Failure to provide that is causing the Xcode log warnings.
For Swift:
var window: UIWindow?
For Objective-C:
#property (strong, nonatomic) UIWindow *window;
In addition, you might have an Application Scene Manifest entry in your Info.plist file - if you do not use scenes, but only a window and view controllers (eg because you want to test something in the old UI setup), you should remove that entry to be able to see your views.
i'm using xcode 6 and they no longer have the "empty project" option when creating a new project, only a single view one...Is there an option to get it or it's gone and I need to deal with it?
Thanks a bunch
You need to deal with it, but it's easy. Start with the Single View application. Delete the storyboard and delete the reference to it in the Info.plist (so that there is no longer a main storyboard). If you like, delete the view controller class as well. Now just do everything from scratch in the app delegate's application:didFinishLaunchingWithOption:, just as you did in Xcode 5.
I'm using Swift these days, so I'll show you what a pure code app delegate launch looks like in Swift; I'm sure you can translate into Objective-C:
import UIKit
#UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame:UIScreen.mainScreen().bounds)
self.window!.rootViewController = ViewController() // or whatever you call it
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
return true
}
}