Migrating UIWebView delegate to WKWebView delegate method

12,704

Solution 1

You might required to implement the following in your code, which means instead of using UIWebViewDelegate protocol try to use WKNavigationDelegate protocol. I guess you are missing one of the most important function when you are handling with sessions.

   func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print(#function)
        completionHandler(.performDefaultHandling,nil)
    }

There are different types of AuthChallengeDisposition , like

public enum AuthChallengeDisposition : Int {


    case useCredential

    case performDefaultHandling

    case cancelAuthenticationChallenge

    case rejectProtectionSpace
}

Complete WKNavigationDelegate protocols are

  extension ViewController: WKNavigationDelegate{
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        print(#function)
    }

    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print(#function)
        completionHandler(.performDefaultHandling,nil)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        print(#function)
        decisionHandler(.allow)
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        print(#function)
        decisionHandler(.allow)
    }
}

Solution 2

I guess you can use webView(_:decidePolicyFor:decisionHandler:) and you block/cancel or allow requests. That should work in the same way.

Disclaimer: I haven't tested that yet, I'll do so as soon as I find some time.

Solution 3

analyzing your code, i have found a statement that is never reached cause of "return" called before.

The statement is:

decisionHandler(.allow)

You can find it as last line of code for the function:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (_: WKNavigationActionPolicy) -> Void)

that you have up this method:

func webViewDidStartLoad(_ webView: UIWebView) {
    numberOfDidStartLoads += 1
}
Share:
12,704

Related videos on Youtube

Siva
Author by

Siva

i'm an iOS Developer... 

Updated on June 22, 2022

Comments

  • Siva
    Siva almost 2 years

    I am working on migrating UIWebView to WKWebView. I have changed all the Delegate methods. I need WKWebView delegate methods equal to below UIWebView delegate method. The app is working fine. but login session is not retaining

    UIWebView:
    
        extension WebViewController: UIWebViewDelegate {
    
        func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    
        guard let url = request.url else {
           return true
        }
    
        guard !url.absoluteString.contains("data:application/pdf") else {
            navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action,
                                                                target: self,
                                                                action: #selector(share(sender:)))
            return true
        }
    
        guard url.pathExtension != "pdf" else {
            let safariVC = SFSafariViewController(url: url)
            safariVC.modalPresentationStyle = .popover
            present(safariVC, animated: true, completion: nil)
            return false
        }
    
        guard url.isLogin() == false else {
            AppDelegate.navigationController.signOut(.sessionOnly)
            return false
        }
    
        guard let mobileSite = url.asMobileSite() else {
            return true
        }
    
        let mobileRedirect = URLRequest(url: mobileSite)
        webView.loadRequest(mobileRedirect)
        return false
    
    }
    
    func webViewDidStartLoad(_ webView: UIWebView) {
        numberOfDidStartLoads += 1
    }
    
    func webViewDidFinishLoad(_ webView: UIWebView) {
        numberOfDidStartLoads -= 1
    }
    
    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        numberOfDidStartLoads -= 1
    }
    }
    

    And i tried below code and getting session expire.

    extension WebViewController: UIWebViewDelegate {
    
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (_: WKNavigationActionPolicy) -> Void) {
    
        guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }
    
        guard !url.absoluteString.contains("data:application/pdf") else {
            navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action,
                                                                target: self,
                                                                action: #selector(share(sender:)))
            decisionHandler(.allow)
            return
        }
    
        guard url.pathExtension != "pdf" else {
            let safariVC = SFSafariViewController(url: url)
            safariVC.modalPresentationStyle = .popover
            present(safariVC, animated: true, completion: nil)
            decisionHandler(.cancel)
            return
        }
    
        guard url.isLogin() == false else {
            AppDelegate.navigationController.signOut(.sessionOnly)
            decisionHandler(.cancel)
            return
        }
    
        guard let mobileSite = url.asMobileSite() else {
            decisionHandler(.allow)
            return
        }
    
        let mobileRedirect = URLRequest(url: mobileSite)
        webView.load(mobileRedirect)
        decisionHandler(.cancel)
        return
    
        decisionHandler(.allow)
    
    }
    
        func webViewDidStartLoad(_ webView: UIWebView) {
            numberOfDidStartLoads += 1
        }
    
        func webViewDidFinishLoad(_ webView: UIWebView) {
            numberOfDidStartLoads -= 1
        }
    
        func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
            numberOfDidStartLoads -= 1
        }
    }
    

    Please help me to resolve this issue. I have made some mistake in changing code from UIWebView to WKWebView.

    • Tamás Sengel
      Tamás Sengel over 6 years
    • Mert Buran
      Mert Buran over 6 years
      can you give more info about the crash? you must call decisionHandler in this method, can the crash be related to that?
    • Siva
      Siva over 6 years
      No. 'App Delegate' Crash. I have added screenshot please see @MertBuran
    • Mert Buran
      Mert Buran over 6 years
      do you have an exception breakpoint while debugging? AppDelegate shouldn't be crashing here
    • Siva
      Siva over 6 years
      No Exception breakpoint.
    • Siva
      Siva over 6 years
      @MertBuran Any idea?
    • Mert Buran
      Mert Buran over 6 years
      i mean you should add an "exception breakpoint" (you can google it with these keywords) to see which line actually crashes, then you can dig deeper to fix the crash. btw, looks like your original question is answered; now you are asking another question. i'd suggest you asking another question on SO instead of merging two different questions into one. hope that helps
    • Siva
      Siva over 6 years
    • shallowThought
      shallowThought over 6 years
      I do not understand the actual issue. How I understand, the app crashes in AppDelegate and you do not know why? Is this correct? Or is session nill at some point ("login session is not retaining")?
    • Siva
      Siva over 6 years
      @shallowThought The issue is session is not retaining.
  • Siva
    Siva over 6 years
    I guess session is not retaining. Same thing working fine in UIWebView. Do you need more info?
  • Bhargav B. Bajani
    Bhargav B. Bajani over 4 years
    @Siva have you got any solution for the session is not retaining?