はじめに
実務の中で、SceneDelegate内で設定したWindowの後に別のWindowを表示する必要があったため、備忘録を残します。
そもそもWindowって何?
Windowとは簡単に言うと、コンテナです。そのコンテナの中に複数のUIViewが配置されることで私達の目に見える状態となっているわけなんです。
実装
それでは、本題に入って行きましょう。
SceneDelegate
// シーンの格納用
var windowScene: UIWindowScene?
// 最初のWindow格納用
var initwindow: UIWindow?
// 次のWidow格納用
var nextWindow: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
windowScene = windowScene
let viewController = FirstViewController // 最初に表示させたいViewController
initwindow = UIWindow(windowScene: windowScene)
initwindow.accessibilityIdentifier = "initWindow"
initwindow = window
initwindow.rootViewController = viewController
initwindow.makeKeyAndVisible()
}
...
...
extension SceneDelegate {
static var shared: SceneDelegate {
let scene = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
return scene
}
/*
* nextWindowを生成
* @param viewController: Windowに設定するUIViewController
*
*/
func createNextWindow(viewController: UIViewController) {
guard let windowScene = sceneWindow else { return }
nextWindow = UIWindow(windowScene: windowScene)
nextWindow?.frame = windowScene.screen.bounds
nextWindow?.accessibilityIdentifier = "nextWindow"
nextWindow?.rootViewController = viewController
nextWindow?.windowLevel = UIWindow.Level.alert + 1
nextWindow?.makeKeyAndVisible()
}
/*
* nextWindowを削除
*
*/
func removeContentWindow() {
nextWindow?.isHidden = true // ウィンドウを非表示にする
nextWindow = nil // ウィンドウの参照を解放する
}
}
呼び出し側
class FirstViewController: UIViewController {
@IBAction func createButton(_ sender: Any) {
// 次の画面のViewControllerをインスタンス化
let nextViewController = SecondViewController()
// Windowを作成
SceneDelegate.shared.createContentWindow(viewController: nextViewController)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
注意事項
もしかしたらこの実装をすると、起動時に画面が正常に表示されず真っ暗な画面のみが表示されることもあるかもしれませんが、その際はターミナルで以下のコマンドを叩いてください。
rm -rf ~/Library/Caches/com.apple.dt.Xcode
rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Developer/XCPGDevices
rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport
上から
・Xcodeのキャッシュファイル
・Xcodeプロジェクトのビルド中に生成された中間ファイルやビルド結果
・Xcodeが使用するデバイスおよびシミュレータに関連する情報
・Xcodeが各iOSデバイスと通信するために使用するサポートファイル
このコマンド達を叩くことで、キャッシュ関係を全て削除します。
おそらくこれで表示されたのではないでしょうか?
最後に
僕自身今までWindowを意識して使うことがなかったので、改めてWindowの重要性を再認識しました。
また、Windowだけでなく基盤の部分をもっと知ることで、設計の幅も広がると思いました。
まだまだ勉強中ですので、間違っている箇所などあればご指摘いただけると幸いです。
参考資料