Xcode11で作成したプロジェクトでは`[UIWindow new]`で生成したWindowが画面に表示されない問題の対処法

Xcode11とUISceneとUIWindowにまつわるトラブルシュートに追われている。
個別のケースに分解してお届け。

## 現象

- Xcode11で作成したプロジェクトをiOS13で実行しているとき、UIWindowが表示されない
- rootViewController持たせて、`viewDidLoad`にbreak pointを貼ったりすると、動作はしていることが確認できる。

## 原因

- Xcode11で作る新規プロジェクトは、Scene Based Lifecycleが有効になっている。
- Scene Based Lifecycleが有効になっていると、`[UIWindow new]`, `[[UIWindow alloc] initWithFrame:]` で生成したwindowは View Hierarchyに載らなくなる
    - UIWindowを載せるべきWindowSceneが不明なため

## 対応

ひとつは、[Xcode11で作成したプロジェクトからSceneに関する機能をオミットする](https://qiita.com/yajamon/items/b72f79237ffb2fc9cdca)方法。

もうひとつは正攻法。（本記事）

`[[UIWindow alloc] initWithWindowScene:]`で windowを生成する。

そのためには、なんらかの手段によって`UIWindowScene`を拾い上げる必要がある。

### ボタンを押した時に表示したいとか、特定のViewと同じUIWindowSceneを選択する場合

```objc:ViewController.m
@interface ViewController ()
@property (nonatomic) UIWindow *window;
@end

@implementation ViewController
- (IBAction)openWindow:(UIButton *)sender {

    UIWindowScene *scene = sender.window.windowScene;
    UIWindow *window = [[UIWindow alloc] initWithWindowScene: scene];

    // 以下は確認用の見た目調整と表示
    UIViewController *viewController = [UIViewController new];
    viewController.view.backgroundColor = UIColer.greenColer;
    window.frame = CGRectMake(20, 20, 50, 50);
    window.rootViewContoller = viewController;

    self.window = window;
    [self.window makeKeyAndVisible];
}
@end
```

```swift:ViewController.swift
class ViewController: UIViewController {
    var window: UIWindow?
    
    @IBAction func openWindow(_ sender: UIButton) {

        guard let scene = sender.window?.windowScene { return }
        let window = UIWindow(windowScene: scene)

        // 以下は確認用の見た目調整と表示
        let viewController = UIViewController()
        viewController.view.backgroundColer = .green
        window.frame = CGRect(x:20, y:20, width:50, height:50)
        window.rootViewContoller = viewController

        self.window = window
        self.window?.makeKeyAndVisible();
    }
}
```

### Sceneは一つだけのアプリである場合など、UIApplicationからUIWindowSceneを引っ張りたい場合

```objc:ViewController.m
@interface ViewController ()
@property (nonatomic) UIWindow *window;
@end

@implementation ViewController
- (IBAction)openWindow:(UIButton *)sender {

    UIWindowScene *scene = (UIWindowScene*)[[[[UIApplication sharedApplication] connectedScenes] allObjects] first];
    UIWindow *window = [[UIWindow alloc] initWithWindowScene: scene];

    // 以下は確認用の見た目調整と表示
    UIViewController *viewController = [UIViewController new];
    viewController.view.backgroundColor = UIColer.greenColer;
    window.frame = CGRectMake(20, 20, 50, 50);
    window.rootViewContoller = viewController;

    self.window = window;
    [self.window makeKeyAndVisible];
}
@end
```

```swift:ViewController.swift
class ViewController: UIViewController {
    var window: UIWindow?
    
    @IBAction func openWindow(_ sender: UIButton) {

        guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene { return }
        let window = UIWindow(windowScene: scene)

        // 以下は確認用の見た目調整と表示
        let viewController = UIViewController()
        viewController.view.backgroundColer = .green
        window.frame = CGRect(x:20, y:20, width:50, height:50)
        window.rootViewContoller = viewController

        self.window = window
        self.window?.makeKeyAndVisible();
    }
}
```

## 参考URL

- https://developer.apple.com/documentation/uikit/uiwindow/3197961-initwithwindowscene