application(_ :configurationForConnecting :options: )メソッドについて調べたことのまとめ
大阪オフィスの山田です。最近、松茸を500円で買ったので、松茸ご飯を作りました。美味しかったです。
application(_:configurationForConnecting:options:)
について、調べたことを備忘録としてまとめておきます。この記事を書いている際に、参考にさせていただいた記事や公式のドキュメントは、この記事の参考
セクションに全てまとめてあります。
開発環境
- Xcode11.1(11A1027)
- macOS10.14.6
調べたことと検証結果
Xcode11.1で新規にプロジェクトを作るとAppDelegate.swiftとSceneDelegate.swiftが追加されていると思います。AppDelegate.swiftの以下のコードに着目します。iOS13から使えるメソッドです。
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions ) -> UISceneConfiguration
このメソッドはSceneが作成される時に、UIKitのための設定を行います。 自動でこのメソッドは作成されますが、実装しなければInfo.plistに定義された設定内容の0番目が、設定に使用されるようです。この設定には、作成するSceneのタイプ、Sceneを管理するオブジェクト、最初に表示するViewControllerを含むStoryboardの情報が含まれます。
このメソッド内で、Info.plistに作成した設定をConfiguration Nameで指定して、出しわけすることが可能です。試してみます。まず、以下のように設定を2つ作っておきます。
Default ConfigurationはMain.storyboard
、Second ConfigurationはTest.storyboard
を設定しています。
続いて、AppDelegate.swift
で以下のように実装します。
// パターン1 func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let config = UISceneConfiguration(name: "Second Configuration", sessionRole: connectingSceneSession.role) return config }
下の方に画面のスクリーンショットを貼っていますが、Second Configurationに定義されているTest.storyboardが読み込まれ、initial viewcontrollerが表示されています。
次のパターンでは、Second Configuration
を読み込んだ後、configのstoryboardに別途設定しています。
// パターン2 func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let config = UISceneConfiguration(name: "Second Configuration", sessionRole: connectingSceneSession.role) config.storyboard = UIStoryboard(name: "Hoge", bundle: .main) return config }
そうすると、Hoge.storyboardが読み込まれ、initial viewcontrollerが表示されます。
前述の通り、このメソッド自体をコメントアウト、あるいは削除するとInfo.plistに記載されている内容の0番を使って設定が行われました。
// パターン3 // func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // let config = UISceneConfiguration(name: "Second Configuration", sessionRole: connectingSceneSession.role) // config.storyboard = UIStoryboard(name: "Hoge", bundle: .main) // return config // }
パターン1 | パターン2 | パターン3 |
---|---|---|
configを取得する際のsessionRoleについて
sessionRole: connectingSceneSession.role
引数に使われている上記の値ですが、実際にrawValue
を見てみると、UIWindowSceneSessionRoleApplication
という値が入っていました。これを検索するとInfo.plistのキー値となっています。Info.plistにもう一度着目すると、Scene Configuration
の下に、External Display Session Role
を追加することが可能となっています。外部ディスププレイセッションが発生した時に、SceneDelegateを切り替えることが可能なように見えます。(筆者は外部ディスプレイを使うアプリを作ったことがないので、この部分は想像です)
configに設定できるdelegateClassについて
以下のようにdelegateClassを指定することで、使用するSceneDelegateのクラスを指定することができます。Info.plistにて指定することも可能です。
この例ではSecondSceneDelegate
クラスを作成し、プログラムから指定しています。
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let config = UISceneConfiguration(name: "Second Configuration", sessionRole: connectingSceneSession.role) config.delegateClass = SecondSceneDelegate.self <- delegateClassの指定 return config }
class SecondSceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let _ = (scene as? UIWindowScene) else { return } } }
なので、application(_:configurationForConnecting:options:)
メソッドの中で条件によってどのSceneDelegate
を使うかを選択することができます。プロパティのDiscussionを見ると、後述するsceneClassがUIWindowScene
クラスである場合は、UIWindowSceneDelegate
に適合したクラスを指定する必要があります。そうでなければUISceneDelegate
に適合したクラスを指定することが可能とのことです。
configに設定できるsceneClassについて
UIKitが作成するSceneオブジェクトのクラスを指定することができます。UISceneあるいはそのサブクラスを指定することができます。実際にSceneDelegate.swiftの中でUIWindowScene
サブクラスが使われています。プロパティのDiscussionの内容を見ると、通常このUIWindowScene
クラスを使うようで、考えてみたものの、他のクラスを使うケースが思いつきませんでした。こちらもInfo.plistに記述することが可能です。
参考
- iOS13のSceneDelegate周りのアプリの起動シーケンス
- iOS13のScene-Basedライフサイクル(UISceneDelegate)
- [iOS13] UIScene APIを使用する [Xcode11]
- Specifying the Scenes Your App Supports
- Scenes
最後に
SceneDelegateも含めて調べてるうちに「iPad欲しいな」ってなりました。