Since iOS 7, the navigation bar and toolbar[0] in a UINavigationController
are designed to render atop the content of the current UIViewController
. In order to prevent these bars from occluding the contents of the view, UINavigationController
will (under certain conditions) automatically reach down the view hierarchy and adjust the insets of the primary UIScrollView
, such that the content is padded by the height of these bars.
The system keyboard is also designed to occlude the bottom half of the screen by default. In most cases, this is undesirable, so the app developer is expected to subscribe to NSNotificationCenter
keyboard events and adjust the UIScrollView
insets themselves.
WKWebView
automatically subscribes to these keyboard events and adjusts its UIScrollView
insets to prevent keyboard occlusion. However, instead of taking the maximum of the keyboard and toolbar height (both of which are anchored at the bottom of the screen), it sums them together, creating extra bottom padding equivalent to the height of the toolbar.
[0] The navigation bar is the bar at the top (which typically contains the screen's title and a 'back' button), and the toolbar is the bar at the bottom (which typically contains action buttons).
The logic to calculate these insets lives in a private helper method on UIScrollView
, so its not clear whether this bug belongs to WKWebView
, UIScrollView
, or UINavigationController
. I believe that this helper method (-[UIScrollView _adjustForAutomaticKeyboardInfo]
) is the place where a MAX(keyboardHeight, contentInset.bottom)
fix should be applied.
The disassembly from UIScrollView
indicates the presence of certain keyboard-related inset properties, which may also possibly be leveraged to solve this problem, though due to the closed-source nature of UIKit, the solution is not immediately clear.
Initially, the main UINavigationController
- inspects the inbound
-[UIViewController automaticallyAdjustsScrollViewInsets]
and returns early if it's set toNO
- calculates the height of the navigation bar and toolbar
- notifies the inbound
UIViewController
of the appropriate adjustments tocontentInset
andscrollIndicatorInset
via this call chain, which it applies to itsUIScrollView
If the current UIViewController
contains a WKWebView
, that WKWebView
- subscribes to
UIKeyboard
notifications at this line, and upon notification - calls
-[UIScrollView _adjustForAutomaticKeyboardInfo]
at this line
Finally, -[UIScrollView _adjustForAutomaticKeyboardInfo]
- obtains the height of the keyboard
- adds it to its current
bottom
value forcontentInset
andscrollIndicatorInset