131

I'm migrating from UIWebView to WKWebView, how can I rewrite these function for WKWebView?

func webViewDidStartLoad(webView: UIWebView){}
func webViewDidFinishLoad(webView: UIWebView){}

and

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    print("webview asking for permission to start loading")
    if navigationType == .LinkActivated && !(request.URL?.absoluteString.hasPrefix("http://www.myWebSite.com/exemlpe"))!{
        UIApplication.sharedApplication().openURL(request.URL!)
        print(request.URL?.absoluteString)
        return false
    }
    print(request.URL?.absoluteString)
    lastUrl = (request.URL?.absoluteString)!

    return true
}


func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
    print("webview did fail load with error: \(error)")
    let testHTML = NSBundle.mainBundle().pathForResource("back-error-bottom", ofType: "jpg")
    let baseUrl = NSURL(fileURLWithPath: testHTML!)
        
    let htmlString:String! = "myErrorinHTML"
    self.webView.loadHTMLString(htmlString, baseURL: baseUrl)
}
stackich
  • 3,607
  • 3
  • 17
  • 41
Phocs
  • 2,430
  • 5
  • 18
  • 35
  • Sounds like you should take a look at the [`navigationDelegate`](https://developer.apple.com/library/ios/documentation/WebKit/Reference/WKWebView_Ref/#//apple_ref/occ/instp/WKWebView/navigationDelegate) of the `WKWebView`. – luk2302 May 29 '16 at 12:46
  • Similar issue - may help you - https://stackoverflow.com/questions/46793618/ios-wkwebview-vs-uiwebview – Krunal Oct 18 '17 at 11:43

3 Answers3

252

UIWebView => WKWebView Equivalent

UIWebViewDelegate => WKNavigationDelegate

delegate => navigationDelegate
didFailLoadWithError => didFailNavigation
webViewDidFinishLoad => didFinishNavigation
webViewDidStartLoad => didStartProvisionalNavigation
shouldStartLoadWithRequest => decidePolicyForNavigationAction

About shouldStartLoadWithRequest you can write:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    print("webView:\(webView) decidePolicyForNavigationAction:\(navigationAction) decisionHandler:\(decisionHandler)")
    
    switch navigationAction.navigationType {
        case .linkActivated:
        if navigationAction.targetFrame == nil {
            self.webView?.loadRequest(navigationAction.request)
        }
        if let url = navigationAction.request.url, !url.absoluteString.hasPrefix("http://www.myWebSite.com/example") {
            UIApplication.shared.open(url)
            print(url.absoluteString)
            decisionHandler(.cancel)
        return
        }
        default:
            break
    }
    
    if let url = navigationAction.request.url {
        print(url.absoluteString)
    }
    decisionHandler(.allow)
}

And for the didFailLoadWithError:

func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    print("webView:\(webView) didFailNavigation:\(navigation) withError:\(error)")
    let testHTML = Bundle.main.path(forResource: "back-error-bottom", ofType: "jpg")
    let baseUrl = URL(fileURLWithPath: testHTML!)

    let htmlString = "myErrorInHTML"
    self.webView.loadHTMLString(htmlString, baseURL: baseUrl)
}
clarkttfu
  • 577
  • 6
  • 11
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • 1
    webViewDidFinishLoad and didFinishNavigation are not exactly the same. The didFinishNavigation method is called before the page is fully loaded. – Michal Cichon Jul 04 '17 at 14:13
  • 1
    documentation says that this method is for osx only. The question was for iOS – Gargo Aug 19 '17 at 19:21
  • 1
    @Gargo Take a look to both the descriptions: [webViewDidFinishLoad](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview?language=objc) , [didFinishNavigation](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview) , as you see is available also for iOS 8.0+ – Alessandro Ornano Aug 19 '17 at 19:39
  • https://stackoverflow.com/questions/46171410/migrating-uiwebview-delegate-to-wkwebview-delegate-method?noredirect=1#comment79308306_46171410 - anyone help me this issue @AlessandroOrnano – Siva Sep 12 '17 at 13:55
  • 5
    Just short note that these methods are declared in `WKNavigationDelegate` (not`WKUIDelegate`). – Mike Keskinov Sep 03 '18 at 17:45
43

Here is the Objective-C methods for the migration:

  1. shouldStartLoadWithRequest -> decidePolicyForNavigationAction

Remember to call the decisionHandler:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
       if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {

       }
       NSString *url = [navigationAction.request.URL query];
                
       decisionHandler(WKNavigationActionPolicyAllow);
}
  1. webViewDidStartLoad -> didStartProvisionalNavigation
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
}
  1. webViewDidFinishLoad -> didFinishNavigation
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
}
  1. didFailLoadWithError -> didFailNavigation
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
}
Pranav Kasetti
  • 8,770
  • 2
  • 50
  • 71
ajw
  • 2,568
  • 23
  • 27
16

Migrating UIWebView to WKWebView, Swift 4:

Equivalent of shouldStartLoadWithRequest:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    var action: WKNavigationActionPolicy?
    
    defer {
        decisionHandler(action ?? .allow)
    }
    
    guard let url = navigationAction.request.url else { return }
    
    print(url)
    
    if navigationAction.navigationType == .linkActivated, url.absoluteString.hasPrefix("http://www.example.com/open-in-safari") {
        action = .cancel                  // Stop in WebView
        UIApplication.shared.open(url)    // Open in Safari
    }
}

Equivalent of webViewDidStartLoad:

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    print(String(describing: webView.url))
}

Equivalent of didFailLoadWithError:

func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    let nserror = error as NSError
    if nserror.code != NSURLErrorCancelled {
        webView.loadHTMLString("404 - Page Not Found", baseURL: URL(string: "http://www.example.com/"))
    }
}

Equivalent of webViewDidFinishLoad:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    print(String(describing: webView.url))
}
AamirR
  • 11,672
  • 4
  • 59
  • 73
  • Small update: in `shouldStartLoadWithRequest` function, `openURL(url)` has been deprecated. It is not just `open(url)` – Joseph Feb 26 '23 at 07:18