WKWebView popup not showing up
I also faced similar issue, mine was popup for connecting facebook won't show in WKWebView but works fine on safari browser.
This code was causing the issue.
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
//This condition was causing the problem while trying to get popup
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
I changed it to following code and it worked
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
if (navigationAction.targetFrame == nil) {
NSURL *tempURL = navigationAction.request.URL;
NSURLComponents *URLComponents = [[NSURLComponents alloc] init];
URLComponents.scheme = [tempURL scheme];
URLComponents.host = [tempURL host];
URLComponents.path = [tempURL path];
if ([URLComponents.URL.absoluteString isEqualToString:@"https://example.com/Account/ExternalLogin"]) {
WKWebView *webViewtemp = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
webViewtemp.UIDelegate = self;
webViewtemp.navigationDelegate = self;
[self.view addSubview:webViewtemp];
return webViewtemp;
} else {
[webView loadRequest:navigationAction.request];
}
}
return nil;
}
Swift version:
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if navigationAction.targetFrame == nil {
let tempURL = navigationAction.request.url
var components = URLComponents()
components.scheme = tempURL?.scheme
components.host = tempURL?.host
components.path = (tempURL?.path)!
if components.url?.absoluteString == "https://example.com/Account/ExternalLogin" {
let webViewtemp = WKWebView(frame: self.view.bounds, configuration: configuration)
webViewtemp.uiDelegate = self
webViewtemp.navigationDelegate = self
self.view.addSubview(webViewtemp)
return webViewtemp
} else {
webView.load(navigationAction.request)
}
}
return nil
}
Hope this helps you
My solution was implementing the WKUIDelegate
and adding the functions for the different scenarios (alerts) that the web view may present:
extension WKWebViewController: WKUIDelegate {
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
completionHandler()
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
completionHandler(true)
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel button"), style: .default, handler: { (action) in
completionHandler(false)
}))
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)
alertController.addTextField { (textField) in
textField.text = defaultText
}
alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default, handler: { (action) in
if let text = alertController.textFields?.first?.text {
completionHandler(text)
} else {
completionHandler(defaultText)
}
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel button"), style: .default, handler: { (action) in
completionHandler(nil)
}))
present(alertController, animated: true, completion: nil)
}
}
I tried the other way round and it worked for me. Here is the code: Create a instance of WebView
fileprivate var webView: WKWebView?
Initialize instance and make assign it to view.
override func loadView() {
webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
webView?.uiDelegate = self
webView?.navigationDelegate = self
view = webView
}
Thereafter, just add the following delegate method:
func webView(_: WKWebView, createWebViewWith _: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures _: WKWindowFeatures) -> WKWebView? {
self.webView?.load(navigationAction.request)
return nil
}
Voila! Everything will work same as UIWebView
.
Note: You won't be able to tap few links on the WebSite, because they would be HTTP instead of HTTPS. WKWebView by default blocks all HTTP requests which aren't secure.
To bypass, just add NSExceptionAllowsInsecureHTTPLoads
as true
in info.plist
file.