8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-10-02

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に関する機能をオミットする方法。

もうひとつは正攻法。(本記事)

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

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

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

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
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を引っ張りたい場合

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
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

8
4
3

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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?