この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
大阪オフィスの山田です。最近、松茸を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欲しいな」ってなりました。