[iOS] UIWindowを追加する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

前回、アラートやキーボードが表示された際の複数のUIWindowについて確認してみましたが、今回は、自分でこのUIWindowを追加して挙動を確認してみました。


参考:[iOS] 複数のUIWindowの挙動を確認する

今回も、iOS9.3で動作確認しておりますが、他のバージョンで挙動が異なる可能性があることは、予めご了承ください。

2 試験準備

前回のテストプログラムに3つほどボタンを追加し、ここにコードを追加することで試験を進めます。 アプリのUIWindowを列挙するログ出力などは、前回と同じです。

001

次に、自前で生成するUIWindowを見た目で区別しやすいように、UIWindowを継承したMyWindowを定義しました。そして、ViewControllerの中で、プロパティとしてこのMyWindowを定義し、ここに生成することにします。

@interface MyWindow : UIWindow
@end

@implementation MyWindow
@end

@interface ViewController ()

@property (strong,nonatomic)MyWindow *myWindow; // プロパティとして定義

@end

3 動作確認

(1) UIWindowの生成

上記の①のところに、次のようなコードを追加してMyWidowを生成してみました。

- (IBAction)tapAppendWindow:(id)sender {
    _myWindow = [MyWindow new];//MyWindowの生成
    _myWindow.frame = CGRectMake(100, 100, 200, 200); // 描画範囲
    _myWindow.backgroundColor = [UIColor.redColor colorWithAlphaComponent:0.2];//背景色をAlpha値0.2の赤色に設定
}

そして、その時の状況は次のとおりです。

まず、起動時は、普通にUIWindowが一つ存在しています。

[Confirm]
Application.windows.count = 1
UIWindow keywindow = 1 hidden=0 lebel=0.000000

そして、MyWindowを生成すると、プロパティに生成しただけなのに、アプリのUIWindowのリストに追加されています。 そう、「アプリのウインドウリストへの追加」のような実装は必要ないようです。

[Confirm]
Application.windows.count = 2
UIWindow keywindow = 1 hidden=0 lebel=0.000000
MyWindow keywindow = 0 hidden=1 lebel=0.000000

しかし、見た目上は、生成したMyWindowを確認することは出来ません。

002

(2) makeKeyAndVisible

次に生成したMyWindowmakeKeyAndVisibleメソッドを呼び出しました。

- (IBAction)tapAppendWindow:(id)sender {
    _myWindow = [MyWindow new];//MyWindowの生成
    _myWindow.frame = CGRectMake(100, 100, 200, 200); // 描画範囲
    _myWindow.backgroundColor = [UIColor.redColor colorWithAlphaComponent:0.2];//背景色をAlpha値0.2の赤色に設定

    [_myWindow makeKeyAndVisible]; // <= この行を追加

}

今度は、追加したMyWindowが表示されていることを確認できます。実際に操作してみると、MyWindowの下に隠れているUIコントロールは、操作できません。

003

ウインドウ状況を確認するとkeywindowが、元のUIWindowから、MyWindowに移動したのが分かります。両方ともレベルが0で同じなので、keywindowであるMyWindowが優先されているのでしょう。

[Confirm]
Application.windows.count = 2
UIWindow keywindow = 0 hidden=0 lebel=0.000000
MyWindow keywindow = 1 hidden=0 lebel=0.000000

(3) Viewの追加

UIWindowには、rootViewControllerというプロパティがあり、ここにViewをセットすることで表示させることができます。

ストーリーボードで、View Controlを1つ追加し、Storyboard IDMyViewControllerとしました。

004

また、画面の中央にボタンを置き、MyViewControllerクラスを作成してボタンを押したことが分かるようにしました。

MyViewController.h

@implementation MyViewController

- (IBAction)tapButton:(id)sender {
    NSLog(@"tap myView");
}

それでは、また、①のコードに追加して、ウインドウの上にビューを載せてみます。

- (IBAction)tapAppendWindow:(id)sender {
    _myWindow = [MyWindow new];//MyWindowの生成
    _myWindow.frame = CGRectMake(100, 100, 200, 200); // 描画範囲
    _myWindow.backgroundColor = [UIColor.redColor colorWithAlphaComponent:0.2];//背景色をAlpha値0.2の赤色に設定

    // ストーリーボードを取得
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    // Storyboard IDからビューを生成
    UIViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewController"];
    // ルートビューとしてセットする
    _myWindow.rootViewController = myViewController;

    [_myWindow makeKeyAndVisible];

}

実行すると、次のようになります。ボタンが押せていることも確認できます。

005

(4) KeyWindowとWindowLebel

次は、元のUIWindowにKeyWindowを戻してみます。 ②のところに、下記のコードを追加しました。

- (IBAction)tapSetKey:(id)sender {
    UIWindow *window = [[UIApplication sharedApplication] delegate].window;
    [window makeKeyAndVisible];
}

実行してみると、ちゃんと、keywindowが戻っています。

[Confirm]
Application.windows.count = 2
UIWindow keywindow = 1 hidden=0 lebel=0.000000
MyWindow keywindow = 0 hidden=0 lebel=0.000000

そして、MyWindowは、見えなくなりました。最初の状態と同じです。

002

ここで、MyWindowのレベルをUIWindowより大きく設定してみます。

_myWindow.windowLevel = 1;
[Confirm]
Application.windows.count = 2
UIWindow keywindow = 1 hidden=0 lebel=0.000000
MyWindow keywindow = 0 hidden=0 lebel=1.000000

005

ちゃんとMyWindow側のボタンも押せることが確認できます。

消去

③に次のコードを書いて実行してみます。単純に参照を消しただけです。

- (IBAction)tapRemoveWindow:(id)sender {
    _myWindow = nil;
}

002

画面上からMyWindowは消え、ウインドウリストからも居なくなっています。また、自動的にUIWindowにkeywindowが移っていることも確認できました。

[Confirm]
Application.windows.count = 1
UIWindow keywindow = 1 hidden=0 lebel=0.000000

4 最後に

今回は、自分でUIWindowを追加することでアプリのUIWindowの動作が、更に見えた気がします。

ここまで来ると、重ね書きを応用して、色々自由に書けそうな気がしてきました。

参考資料


[iOS] 複数のUIWindowの挙動を確認する
UIKit Framework Reference UIWindow Class Reference
iOS開発におけるウィンドウ「UIWindow」の知られざる活用方法とは? #iOS
makeKeyWindow vs makeKeyAndVisible