iOS 新しく作成したプロジェクトから SceneDelegate を削除する#
背景#
Xcode 11 以降、新しいプロジェクトを作成すると、デフォルトで SceneDelegate が含まれていますが、SceneDelegate は iOS 13 以降に導入されたものです。もし最低互換バージョンが iOS 13 未満の場合、どうすればよいのでしょうか?
过程#
まず、SceneDelegate とは何か、なぜ SceneDelegate が必要なのかを見てみましょう。
公式説明:
UISceneSession オブジェクトは、シーンのユニークなランタイムインスタンスを管理します。ユーザーがアプリに新しいシーンを追加するか、プログラム的にリクエストすると、システムはそのシーンを追跡するためのセッションオブジェクトを作成します。セッションにはユニークな識別子とシーンの構成詳細が含まれています。UIKit はシーン自体のライフタイムにわたってセッション情報を維持し、ユーザーがアプリスイッチャーでシーンを閉じると、セッションを破棄します。
セッションオブジェクトを直接作成することはありません。UIKit は、アプリとのユーザーインタラクションに応じてセッションを作成します。また、UIApplication の requestSceneSessionActivation (_:userActivity:options:errorHandler:) メソッドを呼び出すことで、UIKit に新しいシーンとセッションをプログラム的に作成するように依頼することもできます。UIKit は、アプリの Info.plist ファイルの内容に基づいてデフォルトの構成データでセッションを初期化します。
翻訳説明:
Xcode 11 で新しく作成されたプロジェクトで SceneDelegate に関連する部分は以下の通りです:
- AppDelegate クラス内の 2 つの「シーンセッション」メソッド:application (:configurationForConnecting:options:) と application (:didDiscardSceneSessions:)
- ライフサイクルイベント(active、resign、disconnect など)を含む SceneDelegate クラス。
- Info.plist ファイルに「Application Scene Manifest」構成項目が提供されており、アプリのシーンを構成するためのシーン構成名、delegate クラス名、storyboard エントリが含まれています。
SceneDelegate が不要な場合、どう処理すればよいのでしょうか?
2 つの方法があります。
a. SceneDelegate に関連するものを直接削除する
b. システムバージョンに基づいて互換性を判断する
方法一:SceneDelegate を削除する
- AppDelegate 内の UISceneSession Lifecycle の 2 つのデリゲートメソッドを削除し、window プロパティを追加し、application:didFinishLaunchingWithOptions: メソッド内で window を初期化し、ルートビューを設定します。
- SceneDelegate ファイルを削除します。
- ターゲットを選択し、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 {
// アプリケーション起動後のカスタマイズのためのオーバーライドポイント。
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = HXBaseViewController()
self.window?.makeKeyAndVisible()
return true
}
}
方法二:システムバージョンに基づいて互換性を判断しますが、この方法では注意が必要です。iOS 13 以降では、一部のプログラム状態の処理は SceneDelegate 内で行う必要があります。
- まず SceneDelegate に @available (iOS 13, *) の宣言を追加します。
- 次に、AppDelegate 内の UISceneSession Lifecycle の 2 つのデリゲートメソッドを別の Extension に書き、@available (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 {
// アプリケーション起動後のカスタマイズのためのオーバーライドポイント。
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 {
// 新しいシーンセッションが作成されるときに呼び出されます。
// このメソッドを使用して、新しいシーンを作成するための構成を選択します。
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// ユーザーがシーンセッションを破棄したときに呼び出されます。
// アプリケーションが実行されていない間にセッションが破棄された場合、application:didFinishLaunchingWithOptionsの直後に呼び出されます。
// 破棄されたシーンに特有のリソースを解放するためにこのメソッドを使用します。
}
}