支持 iOS 12 和 13 时的 AppDelegate 和 SceneDelegate
AppDelegate and SceneDelegate when supporting iOS 12 and 13
我需要支持 iOS 12 和 iOS 13。
我应该在 AppDelegate
和 SceneDelegate
之间复制代码吗?
例如:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
}
和
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
如果我不这样做,在第一个版本中我会以黑屏结束,但如果我这样做并在 HomeViewController
的 viewDidLoad
方法中打印,我可以看到它被称为两次。
我更新了我的 didFinishLaunchingWithOptions
,我可以在 iOS13
中看到它仍然被调用了两次。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
guard #available(iOS 12, *) else { return true }
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
您确实需要复制代码,但您需要确保它 运行 仅在正确的系统上。在 iOS 13 中,您不希望应用程序将 didFinishLaunching
主体代码委托给 运行,因此使用可用性检查来防止它。
以同样的方式,使用可用性从 iOS 12.
隐藏 window 场景内容
这是 运行 在 iOS 12 和 iOS 13 上都正确的解决方案的基本草图:
AppDelegate.Swift
import UIKit
@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey : Any]?)
-> Bool {
if #available(iOS 13, *) {
// do only pure app launch stuff, not interface stuff
} else {
self.window = UIWindow()
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
return true
}
}
SceneDelegate.swift
import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window : UIWindow?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
}
}
ViewController.swift
import UIKit
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("view did load")
self.view.backgroundColor = .green
}
}
请注意,处理其他重复项(例如应用程序激活)要简单得多,因为如果您支持 window 场景,则不会在 iOS 12 上调用应用程序委托方法。所以问题仅限于这种情况,即您有 window / 根视图控制器操作要在启动时执行(例如,没有故事板)。
Xcode 11.* 和 Swift 5.*
按照下面给出的步骤,您的代码将适用于 iOS 12 和 iOS 13 -
- 从 info.plist 文件中删除场景清单
- 移除场景委托
- 在 AppDelegate
中添加 window 属性
- 从 AppDelegate 中删除与场景相关的所有方法(主要是 2 个方法)
希望这对某些人有用。快乐编码
这是我的作品。
@可用 SceneDelegate.swift
由于 SceneDelegate class 仅在 iOS 13 及更高版本上可用,我们必须告诉编译器仅包含 iOS 13 及更高版本的 class .为此,我们将在 SceneDelegate class 声明的正上方添加这一行“@available(iOS 13.0, *)”,如下所示:
import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}
@可用AppDelegate.swift
中的一些方法
接下来AppDelegate.swift新增了两个方法,只支持iOS13及以上。我们还将在它们之上添加相同的 @available(iOS 13.0, *) :
// 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.
}
将 window 添加回 AppDelegate
如果您现在构建并 运行 您的应用程序,您将看到黑屏,因为没有初始化 UIWindow。
在 iOS 12 和更早的版本中,总是有一个 var window: UIWindow?位于 AppDelegate.swft 顶部的变量。 iOS 13 已将此变量移至 SceneDelegate.swift,现在我们要将此变量添加回 AppDelegate。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// ...
}
现在在 iOS 12 台设备上构建并 运行 您的应用程序,并且可以正常工作!
我猜 Apple 真的希望 iOS 开发人员采用并专注于 iOS 13,以至于他们不介意默认破坏对 iOS 12 及更早版本的支持Xcode.
中的设置
如果你懒得每次都手动做这些步骤,你也可以在Apple的开发者下载门户下载Xcode10.3(需要用你的Apple ID登录),新建一个Xcode 项目,然后使用 Xcode 11.
对其进行编辑
我需要支持 iOS 12 和 iOS 13。
我应该在 AppDelegate
和 SceneDelegate
之间复制代码吗?
例如:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
}
和
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
如果我不这样做,在第一个版本中我会以黑屏结束,但如果我这样做并在 HomeViewController
的 viewDidLoad
方法中打印,我可以看到它被称为两次。
我更新了我的 didFinishLaunchingWithOptions
,我可以在 iOS13
中看到它仍然被调用了两次。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
guard #available(iOS 12, *) else { return true }
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = HomeViewController()
window.makeKeyAndVisible()
self.window = window
return true
}
您确实需要复制代码,但您需要确保它 运行 仅在正确的系统上。在 iOS 13 中,您不希望应用程序将 didFinishLaunching
主体代码委托给 运行,因此使用可用性检查来防止它。
以同样的方式,使用可用性从 iOS 12.
这是 运行 在 iOS 12 和 iOS 13 上都正确的解决方案的基本草图:
AppDelegate.Swift
import UIKit
@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey : Any]?)
-> Bool {
if #available(iOS 13, *) {
// do only pure app launch stuff, not interface stuff
} else {
self.window = UIWindow()
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
return true
}
}
SceneDelegate.swift
import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window : UIWindow?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let vc = ViewController()
self.window!.rootViewController = vc
self.window!.makeKeyAndVisible()
self.window!.backgroundColor = .red
}
}
}
ViewController.swift
import UIKit
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("view did load")
self.view.backgroundColor = .green
}
}
请注意,处理其他重复项(例如应用程序激活)要简单得多,因为如果您支持 window 场景,则不会在 iOS 12 上调用应用程序委托方法。所以问题仅限于这种情况,即您有 window / 根视图控制器操作要在启动时执行(例如,没有故事板)。
Xcode 11.* 和 Swift 5.*
按照下面给出的步骤,您的代码将适用于 iOS 12 和 iOS 13 -
- 从 info.plist 文件中删除场景清单
- 移除场景委托
- 在 AppDelegate 中添加 window 属性
- 从 AppDelegate 中删除与场景相关的所有方法(主要是 2 个方法)
希望这对某些人有用。快乐编码
这是我的作品。
@可用 SceneDelegate.swift
由于 SceneDelegate class 仅在 iOS 13 及更高版本上可用,我们必须告诉编译器仅包含 iOS 13 及更高版本的 class .为此,我们将在 SceneDelegate class 声明的正上方添加这一行“@available(iOS 13.0, *)”,如下所示:
import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}
@可用AppDelegate.swift
中的一些方法接下来AppDelegate.swift新增了两个方法,只支持iOS13及以上。我们还将在它们之上添加相同的 @available(iOS 13.0, *) :
// 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.
}
将 window 添加回 AppDelegate
如果您现在构建并 运行 您的应用程序,您将看到黑屏,因为没有初始化 UIWindow。
在 iOS 12 和更早的版本中,总是有一个 var window: UIWindow?位于 AppDelegate.swft 顶部的变量。 iOS 13 已将此变量移至 SceneDelegate.swift,现在我们要将此变量添加回 AppDelegate。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// ...
}
现在在 iOS 12 台设备上构建并 运行 您的应用程序,并且可以正常工作!
我猜 Apple 真的希望 iOS 开发人员采用并专注于 iOS 13,以至于他们不介意默认破坏对 iOS 12 及更早版本的支持Xcode.
中的设置如果你懒得每次都手动做这些步骤,你也可以在Apple的开发者下载门户下载Xcode10.3(需要用你的Apple ID登录),新建一个Xcode 项目,然后使用 Xcode 11.
对其进行编辑