UIWindow in iOS

Jai
4 min readOct 7, 2021

--

Task : To Present a UIView above all the view in application including keyboard

In iOS we have two transitions to navigate to another page
Push and present

Push maintains a navigation stack to push the controller on stack and pop up the controller on dismiss

Presenting a controller just present the controller above the rootController

When I tried to present the view above all controllers I thought it to present above the rootController of Window but I failed because the presenting controller which is visible controller is not the rootController of the window.

Presented a controller

Presenting a controller created 7 layers of view above the rootController of the window and then presented controller is above the 7 layer.

Pushed a controller

Pushing a controller replace the previous controller and present the screen above the navigation Controller. There is no dozens of layer like presenting a controller.

I don’t wanna care about transitions if I presenting the view in windows. It succeeds in present the view above all the views but it fails in keyboard.

So I dive into the hierarchy of the application and I found that keyboard is presenting in separate window which have higher level than the keyWindow which contains all the controllers of our application.

Before keyboard arise
Separate window for keyboard while showing keyboard

There is UITextEffectsWindow will look into it later on this post

Keyboard dismissed and UIKeyboardWindow dismissed from hierarchy.

Hurray! I found a way to display a view in top of application. I can present a view in UIApplication.shared.windows.last. So, I can present a view above keyboard or whatever window which is visible in application.

Here comes the iOS native controllers like SKStoreProductViewController and INUIAddVoiceShortcutViewController(Native SiriController) came to play.

Hierarchy when native controllers presented

Those controllers are presented inside the keyWindow. But why there is a UIKeyboard window.

I failed again when I presented these screen. The blockView which I need to add above all view is added in keyboard window which is not at all visible in the application.

Ok let’s add the view in keyWindow and check for this case.

added blockView in keywindow

The blockView is added above the SKStoreProductViewController but not above the keyboard.

So, To add the blockView above the keyboard we need to add the view in UIApplication.shared.windows.last but the view is not added when we present native controllers. Lets dismiss the controllers and check for the UIWindowScenes.

Hierarchy after dismiss the SKStoreProductViewController

There is no SKStoreProductViewController in hierarchy but still the UIKeyboardWindowScene is presented in the list even if there is no keyboard.

So when the window will dismissed? — After keyboard arise and hide

Until then If I add the blockView in UIApplication.shared.windows.last I couldn’t see the block View and it also Freeze the app I couldn’t do anything.

So presenting the blockView above KeyboardWindow, only if keyboard is appearing else present over the keyWindow will move our progress to complete the task. But how to find if keyboard is visible without triggering the notification for every keyboardWillShow and keyboardWillHide and save the state of keyboard?

Let’s check for Height of keyboard in both state. Oops the heights are same in both the state(Keyboard shown and hidden).

But the frame of the keyboard is changing while dismissing and presenting the keyboard.

So we can detect the keyboard state by yPosition of the keyboard frame. Present the block view in UIKeyboardWindow if there is a keyboard or present it in keyWindow succeeded the task.

UITextEffectsWindow

Keyboard Hierarchy

Keyboard is drawn by binding a two image view

Two Images binded to make keyboard
Keyboard TextEffectWindow

There is a placeholder for a keyboard to present in UITextEffectWindow

--

--