WKWebView
Communication Latency Revisited
#
Earlier this year I posted about WKWebView
communication latency and how it’s not quite as good as UIWebView
(when using WKScriptMessageHandler
, the officially sanctioned mechanism). There have a been a few developments in this area, so an update seems warranted.
Things appear to be promising for iOS 9: In late June Mark Lam fixed ScriptMessageHandlerDelegate::didPostMessage
to reuse JSContext
instances across calls. Now that I had an Apple engineer to bug appeal to, I filed a bug asking for same fix to be applied to [WKWebView evaluateJavaScript:completionHandler:]
, to help with execution round trips. Mark kindly obliged, and the fix was picked up (merged?) for iOS 9 beta 4.
Earlier, in April, Ted Suzman emailed me to ask if I’d considered modifying document.title
to send data from the JS side (since it’s mirrored on the native side as the title
property on the WKWebView
, which can be observed via KVO). I implemented this approach and it seemed to work quite well. Ted also suggested trying location.replace
(instead setting location.hash
), which (though it should be equivalent) ends up being slightly faster for both UIWebView
and WKWebView
(implementation).
Ted’s messages got me thinking about other WKWebView
properties that could be manipulated from the JS side, and so I took a closer look at the delegate protocols. The webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:
method on WKUIDelegate
caught my eye. We don’t use window.alert()
in Quip, but this seemed like it would provide a way of getting a string from JS to native with minimal overhead (as previously mentioned, Quip encodes all JS ↔ native communications as strings already, so we don’t want the web view to do any other serialization for us). Better yet webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:
(which maps to window.prompt()
) allows the native side to return a value to the JS side. I implemented these two approaches too.
Here are the results from testing the various communication mechanisms using my test bed. Tests were run on iPad Air 2’s, one running iOS 8.4 and another running iOS 9.0 beta 5
Method/OS | iOS 8.4 | iOS 9.0 beta 5 |
---|---|---|
UIWebView |
||
location.hash |
0.26 | 0.28 |
location.replace |
0.18 | 0.18 |
WKWebView |
||
WKScriptMessageHandler |
2.94 | 0.63 |
location.hash |
0.69 | 0.58 |
location.replace |
0.46 | 0.51 |
document.title |
0.57 | 0.63 |
window.alert() |
0.42 | 0.46 |
window.prompt() |
0.37 | 0.45 |
JS execution round-trip | ||
UIWebView |
0.17 | 0.16 |
WKWebView |
2.60 | 0.39 |
Quip is still using UIWebView
since we’re still supporting iOS 7 (and supporting both web views did not seem like it would be worth the complexity). However, once iOS 9 is released we will most likely drop iOS 7 support, so it’s good to know that switching to WKWebView
will not pose an unreasonable latency burden (though it remains to be seen if the selective swizzling and subview spelunking that we do will carry over).
8 Comments
Post a Comment