[iOS] Handling popup/new window inside web view
Have you ever clicked some links inside your web view and nothing happens, or when you clicked login with social network button (Facebook, Google,…) and a white page appears out of nowhere? Because right now, web view does not support new windows like normal browsers. It’s when we have to handle it ourselves.
I create a simple web page here (with all of the above cases) for the demo project which you can find at the end of this article. Feel free to use it for your own testing project if you want to.
Solution 1: Using javascript injection
In this solution, every time the web view opens a web page (don’t forget to add WKNavigationDelegate
for this web view), we will inject a javascript code block into that page to override window.open()
function, so instead of opening a new window, it just loads that new url in that same window
webView.evaluateJavaScript("window.open = function(open) { return function (url, name, features) { window.location.href = url; return window; }; } (window.open);", completionHandler: nil)
We also need to inject a javascript code block to handle closing the dialog by using url scheme, so when the popup is closed the web view controller will be dismissed
webView.evaluateJavaScript("window.close = function() { window.location.href = 'myapp://closewebview'; }", completionHandler: nil)
The whole block of code should look like this
For <a href="http://a_hyper_link" target="_blank">Display name</a>
we can use WKUIDelegate
to load request of new window in that current window of web view
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if !(navigationAction.targetFrame?.isMainFrame ?? false) {
webView.load(navigationAction.request)
}
return nil
}
The downside of this solution is that you have to handle every javascript function which creates a new window inside web view. There is a better one, solution 2!
Solution 2: Adding sub view
With this solution, when we create the web view we must create from WKPreferences
with javaScriptCanOpenWindowsAutomatically
flag set to true
, this will allow web page to open popup
Then every time this web view wants to create a new window, we create a popup web view for that window and add it to current view hierarchy
… so when user closes the popup, we just have to remove the popup web view
Demo project for solution 2 (which I find it better) can be found here: https://github.com/kentwinder/WebView-Optimization