In Xcode 11, I created a new app project from the Single View App template. I want this app to run in iOS 12 as well as iOS 13. But when I switch the deployment target to iOS 12, I got a lot of error messages like this one:
UIWindowScene is only available in iOS 13 or newer
What should I do?
The template in Xcode 11 uses a scene delegate. Scene delegates and the related classes are new in iOS 13; they don't exist in iOS 12 and before, and the launch process is different.
To make a project generated from an Xcode 11 app template backward compatible, you need to mark the entire SceneDelegate class, and any methods in the AppDelegate class that refer to UISceneSession, as #available(iOS 13.0, *).
You also need to declare a window property in the AppDelegate class (if you don't do that, the app will run and launch but the screen will be black):
var window : UIWindow?
The result is that when this app runs in iOS 13, the scene delegate has the window, but when it runs in iOS 12 or before, the app delegate has the window — and your other code may then need to take account of that in order to be backward compatible.
Could you please add this line code like the following
STEP1:-
#available out the SceneDelegate.swift
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}
STEP2:-
#available out some methods in AppDelegate.swift
// AppDelegate.swift
#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.
}
STEP3:-
You should declare window property in AppDelegate.swift file
like var window: UIWindow?
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
}
Related
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
I have the following declaration in my AppDelegate.swift file.
var window: UIWindow?
and I want to include it only when the deployment target is set to below iOS 13.0. I have looked at
#available(...)
attribute but I don't think it can do what I want. Essentially I want to be able to build my project for iOS 12 or iOS 13 with the minimum number of changes to my project in AppDelegate.swift and SceneDelegate.swift. I have made changes already to AppDelegate.swift and SceneDelegate.swift using #available(iOS 13.0, *) and #available(iOS 13.0, *) but I still need to be able to exclude this other declaration when the deployment target is above iOS 12.
Here is my AppDelegate.swift file:
import UIKit
import Firebase
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? // only include for builds < iOS 13.0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
// Do nothing
} else {
window = UIWindow() // only include for builds < iOS 13.0
window?.rootViewController = UINavigationController(rootViewController: LoginController()) // only include for builds < iOS 13.0
window?.makeKeyAndVisible() // only include for builds < iOS 13.0
}
FirebaseApp.configure()
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.
}
}
and here is my SceneDelegate.swift file:
import UIKit
#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 = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: scene)
window?.rootViewController = UINavigationController(rootViewController: LoginController())
window?.makeKeyAndVisible()
}
// ...
}
Essentially all I want to have happen is I just change the deployment target and the appropriate bits of code get included or excluded in the build process.
var window: UIWindow? // only include for builds < iOS 13.0
Just leave the declaration alone. On iOS 12 and before it will refer to the app window. On iOS 13 and later it will be nil and no harm done.
I am trying to make an Xcode project that was set up for iOS 13 work with a target of iOS 10 or even 12. I'm using Xcode 10 for Swift 3 compatibility.
According to the advice here: Xcode 11 backward compatibility I have added #available(iOS 13.0, *) in the places it was recommended to add it, and I have also declared var window : UIWindow? in the AppDelegate class.
// MARK: UISceneSession Lifecycle
#available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
...
#available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
In Scene Delegate:
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
But I am getting:
Use of undeclared type 'UISceneConfiguration', 'UIWindowSceneDelegate', 'UIScene', 'UISceneSession'
How can I fix this? I don't see what else I can do.
I'm using Xcode 10 for Swift 3 compatibility.
That’s the problem. You cannot mention iOS 13 classes using Xcode 10. It knows nothing about them. You must work entirely within Xcode 11 if you want to link against the iOS 13 SDK.
In Xcode 11, I created a new app project from the Single View App template. I want this app to run in iOS 12 as well as iOS 13. But when I switch the deployment target to iOS 12, I got a lot of error messages like this one:
UIWindowScene is only available in iOS 13 or newer
What should I do?
The template in Xcode 11 uses a scene delegate. Scene delegates and the related classes are new in iOS 13; they don't exist in iOS 12 and before, and the launch process is different.
To make a project generated from an Xcode 11 app template backward compatible, you need to mark the entire SceneDelegate class, and any methods in the AppDelegate class that refer to UISceneSession, as #available(iOS 13.0, *).
You also need to declare a window property in the AppDelegate class (if you don't do that, the app will run and launch but the screen will be black):
var window : UIWindow?
The result is that when this app runs in iOS 13, the scene delegate has the window, but when it runs in iOS 12 or before, the app delegate has the window — and your other code may then need to take account of that in order to be backward compatible.
Could you please add this line code like the following
STEP1:-
#available out the SceneDelegate.swift
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}
STEP2:-
#available out some methods in AppDelegate.swift
// AppDelegate.swift
#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.
}
STEP3:-
You should declare window property in AppDelegate.swift file
like var window: UIWindow?
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
}
In Xcode 11, I created a new app project from the Single View App template. I want this app to run in iOS 12 as well as iOS 13. But when I switch the deployment target to iOS 12, I got a lot of error messages like this one:
UIWindowScene is only available in iOS 13 or newer
What should I do?
The template in Xcode 11 uses a scene delegate. Scene delegates and the related classes are new in iOS 13; they don't exist in iOS 12 and before, and the launch process is different.
To make a project generated from an Xcode 11 app template backward compatible, you need to mark the entire SceneDelegate class, and any methods in the AppDelegate class that refer to UISceneSession, as #available(iOS 13.0, *).
You also need to declare a window property in the AppDelegate class (if you don't do that, the app will run and launch but the screen will be black):
var window : UIWindow?
The result is that when this app runs in iOS 13, the scene delegate has the window, but when it runs in iOS 12 or before, the app delegate has the window — and your other code may then need to take account of that in order to be backward compatible.
Could you please add this line code like the following
STEP1:-
#available out the SceneDelegate.swift
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}
STEP2:-
#available out some methods in AppDelegate.swift
// AppDelegate.swift
#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.
}
STEP3:-
You should declare window property in AppDelegate.swift file
like var window: UIWindow?
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
}