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.
Presenting a controller created 7 layers of view above the rootController of the window and then presented controller is above the 7 layer.
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.
There is UITextEffectsWindow will look into it later on this post
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.
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.
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.
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 is drawn by binding a two image view
There is a placeholder for a keyboard to present in UITextEffectWindow