iOS 删除新创建项目中的 SceneDelegate#
背景#
Xcode 11 之后新建工程,默认为有 SceneDelegate,但是 SceneDelegate 是从 iOS 13 之后才有的,如果最低兼容版本到 iOS 13 以下,需要怎么做呢?
过程#
首先来看一下,SceneDelegate 是什么,为什么会有 SceneDelegate
官方说明:
A UISceneSession object manages a unique runtime instance of your scene. When the user adds a new scene to your app, or when you request one programmatically, the system creates a session object to track that scene. The session contains a unique identifier and the configuration details of the scene. UIKit maintains the session information for the lifetime of the scene itself, destroying the session in response to the user closing the scene in the app switcher.
You do not create session objects directly. UIKit creates sessions in response to user interactions with your app. You can also ask UIKit to create a new scene and session programmatically by calling the requestSceneSessionActivation(_:userActivity:options:errorHandler:) method of UIApplication. UIKit initializes the session with default configuration data based on the contents of your app's Info.plist file.
翻译解释:
Xcode 11 新创建的项目涉及到 SceneDelegate 的地方如下:
- AppDelegate 类中两个 “scene sessions” 方法:application (:configurationForConnecting:options:) 和 application (:didDiscardSceneSessions:)
- 一个 SceneDelegate 类,其中包括生命周期事件,例如 active,resign 和 disconnect。
- Info.plist 文件中提供了”Application Scene Manifest“配置项,用于配置 App 的场景,包括它们的场景配置名,delegate 类名和 storyboard 入口
那不需要 SceneDelegate,要怎么处理?
两种方法,
a. 一种是直接把 SceneDelegate 相关的删除
b. 另外一种则是根据系统版本判断兼容
方法一:删除 SceneDelegate
- 把 AppDelegate 中 UISceneSession Lifecycle 的两个代理方法删除,添加 window 属性,在 application:didFinishLaunchingWithOptions: 方法中初始化 window,设置根视图
- 删除 SceneDelegate 文件
- 选中 target,切换到 info,删除 Application Scene Manifest 这行
/// AppDelegate.Swift
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = HXBaseViewController()
self.window?.makeKeyAndVisible()
return true
}
}
方法二:根据系统版本判断兼容,但是这种方法要注意,iOS 13 之后有些程序状态的处理要在 SeceneDelegate 中
- 首先在 SceneDelegate 中加入 @available (iOS 13, *) 的声明,
- 然后把 AppDelgate 中 UISceneSession Lifecycle 的两个代理方法写到单独的 Extension 中,然后声明 @avaiable (iOS 13, *),
- AppDelegate 的启动方法中也需要修改,编译即可
// SceneDelegate.swift
import UIKit
@available(iOS 13, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
xxx
}
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if #available(iOS 13.0, *) {
// 不需要处理,走SceneDelegate
}
else {
// 初始化UIWindow
window = UIWindow.init()
window?.frame = UIScreen.main.bounds
window?.makeKeyAndVisible()
window?.rootViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateInitialViewController()
}
return true
}
}
@available(iOS 13, *)
extension 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.
}
}