【iOS】UIWindowを使ってキーボードやアラート、ステータスバーの上にViewを出す【Objective-C】

2020年8月29日

iosでのアプリ開発をしているとキーボードの上やステータスバーの上に独自のviewを表示したくなる時がごく稀にあります。こういった場合の時はUIWindowを使って実装していきましょう。

UIWindowに独自のViewを表示しキーボードやアラートより前に表示させる

実装方法です。

// 既存のwindowから新規windowを作成。新規windowのサイズは既存windowと一緒
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
UIWindow *newWindow = [[UIWindow alloc] initWithFrame:currentWindow.frame];
// windowLevelをキーボードやアラートより高く設定する
newWindow.windowLevel = 100000000;
// windowの表示
[newWindow makeKeyAndVisible];

// 独自viewをwindowに追加
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width)];
view.backgroundColor = [UIColor yellowColor];
[newWindow addSubview:view];

もし何も変化がない場合はnewWindowが破棄されないようにクラスで宣言しておきましょう。

一度作ったUIWindowは明示的に指定して破棄するように心がけるとよいでしょう。
破棄のしかたはnilを設定するだけみたいです。

newWindow = nil;

UIWindowについて

手っ取り早く答えを書きましたが、そもそもUIWindowってどうなってるんだ?と思う人も多いかもしれません。そこでまずUIWindowについて簡単に説明していきます。

StoryBordを使わない人ならAppDelegateでよく見かけていると思いますが、UIWindowを使う機会なんてほとんどないので、どうゆうものかよくわからないと思います。

ですが安心してください、とても簡単です。

UIWindowはViewやViewContorllerと同じように複数によって構成されています。
現在の構成はwindowsで確認できます。

NSLog(@"app's windows = %@", [UIApplication sharedApplication].windows);

キーボードやアラートを表示した場合、windowsの数が増えたりするのが確認できます。
試してみてください。

またUIWindowにはwidowsの他にwindowLevelというものがあります。
これは複数のUIWindowが存在した場合、どちらをより最前面に表示するか、というものです。

みなさんが何気なく使っているキーボードやアラートが常に最前面に表示されているのは、このwindowLevelが関係しているからなんです。

windowLevelを調べるにはこのように記述します。

NSLog(@"window = %@, windowLevel = %@",[UIApplication sharedApplication].window, @([UIApplication sharedApplication].window.windowLevel));

appdelegateで使っているwindowのwindowLevelを調べましたが、windowsをfor inで回せば全てのwindowのwindowLevelが確認できます。

windowLevelは初期で3つ用意されています

UIWindowLevelNormal; = 0
UIWindowLevelAlert; = 2000
UIWindowLevelStatusBar; = 1000

ちなみに上記にないキーボードのwindowLevelは10000000みたいです。
べらぼうに高いですね、、、

ということで、独自に実装したUIWindowのwindowLevelを高く設定してその上に独自のviewを追加してあげれば、キーボードやアラートよりも上に独自のviewを表示させることができるというわけですね。