WKWebView Navigation

WKNavigationDelegate

WKNavigationDelegate provides lifecycle hacks for WKWebView.

We can interrupt navigation process and change behaviors using delegation methods.

Details : WKNavigationDelegate

What kind of things we can do

  • Show additional errors when load has errors
  • After finish loading, show page title
  • Hook not http protocol open it with different way

etc…

WKNavigationDelegate methods

didCommit Start to receive web content
didStartProvisionalNavigation Start load in a web view
didReceiveNeeds to response Authentication challenge
didFailError occurs during navigation
didFailProvisionalNavigationError occurs when web view is loading contents
didFinishNavigation is completed
webViewWebContentProcessDidTerminate Web content process is terminated
decidePolicyFor Decide whether to allow or cancel a navigation after its response is known

Example

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
    
    @IBOutlet weak var webView: WKWebView!  // interface builder 10.x
    
    var list = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        list.append("tel")
        list.append("mailto")
        list.append("itms://")
        list.append("itms-apps://")
        
        self.load(urlStr: "https://www.google.com")
        webView.navigationDelegate = self
    }
    
    private func load(urlStr: String) {
        guard let url = URL(string: urlStr) else { return }
        let request = URLRequest(url: url)
        webView.load(request)
    }

// WKNavigationDelegate
    
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        // Called when the web view begins to receive web content.
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        // Called when web content begins to load in a web view.
        print("Start Web : didStartProvisionalNavigation")
    }
    
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // Called when the web view needs to respond to an authentication challenge.
        completionHandler(.performDefaultHandling, nil) // Needed when missing, crash
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        // Called when an error occurs during navigation.
        if let url = webView.url {
            print("Failed url \(url)")
        }
    }
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        // Called when an error occurs while the web view is loading content.
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // Called when the navigation is complete.
        print("Finsh Web : didFinish")
        print("Title : \(webView.title)")
        
        if let url = webView.url {
            print(url)
        }
    }
    
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        // Called when the web view’s web content process is terminated.
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // Decides whether to allow or cancel a navigation after its response is known.
       
//        decisionHandler(.cancel)  // Cancel
        
        if let url = navigationAction.request.url {
            
            // tel, mailto
            // itms://
            // itms-apps://
            for target in list {
                if (url.absoluteString.starts(with: target)) {
                    let app = UIApplication.shared
                    if app.canOpenURL(url) {
                        app.open(url)
                    }
                    decisionHandler(.cancel)
                    return
                }
            }
        }
        decisionHandler(.allow) // Needed when missing, crash
    }
}
iOS
スポンサーリンク
Professional Programmer2

コメント