9

I've been working on a simple app that makes a webview of a website where students can take exams.

So basically the problem I have is that when students are done, they have to click on a button that will send the answers. A popup will appear to make them confirm. https://i.stack.imgur.com/5GhB8.png Except that it doesn't show up. Nothing happens when the button is pushed. It works flawlessly on Safari and I've noticed that it works on the deprecated webview (UIWebview) but I've been trying to make it work on WKWebView.

I'm definitely no swift expert so I apologize if the answer is easy. I've been trying to find some answers about my problem but I'm not sure how to implement it.

Thank you in advance for any help,

import UIKit
import WebKit

class webViewController: UIViewController {

    @IBOutlet weak var webview: WKWebView!

    override func viewDidLoad() {

        super.viewDidLoad()

        let lien = "***"
        if let url = URL(string: lien) {
            let request = URLRequest(url: url)
            _ = webview.load(request);
        }
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
Notsu
  • 93
  • 1
  • 1
  • 4

4 Answers4

6

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

George
  • 3,600
  • 2
  • 26
  • 36
4

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)
    }

}
jastrada
  • 384
  • 1
  • 8
3

When web view demands the new popup window than UIDelegate of WKWebView will come in picture.

Follow these steps to show POP-Up view in WKWebView

  1. Take a another web-view

    private var popupWebView: WKWebView?
    
  2. Assign the uiDelegate of your main web-view to self

    webView?.uiDelegate = self
    
  3. Confirm the WKUIDelegate of to your controller

    extension PaisaPalVC: WKUIDelegate {
        func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
            popupWebView = WKWebView(frame: view.bounds, configuration: configuration)
            popupWebView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            popupWebView?.navigationDelegate = self
            popupWebView?.uiDelegate = self
            if let newWebview = popupWebView {
                view.addSubview(newWebview)
            }
            return popupWebView ?? nil
        }
        func webViewDidClose(_ webView: WKWebView) {
            webView.removeFromSuperview()
            popupWebView = nil
        }
    }
    

Hope this helps you

manvendra singh
  • 296
  • 3
  • 9
2

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.

Bhanu Birani
  • 1,286
  • 1
  • 13
  • 22