0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SceneDelegate内で複数のWindowを使用する方法

Posted at

はじめに

実務の中で、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だけでなく基盤の部分をもっと知ることで、設計の幅も広がると思いました。

まだまだ勉強中ですので、間違っている箇所などあればご指摘いただけると幸いです。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?