天天看点

学习笔记:WKWebView之WKNavigationDelegate (Swift)

WKWebView之WKNavigationDelegate (Swift)

此代理实现的方法可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。

WKNavigationDelegate:

1、下面的方法在跳转时触发

    在接到请求地址,未开始请求前

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

    允许请求,开始请求

    optionalpublicfunc webView(_ webView:WKWebView, decidePolicyFor navigationResponse:WKNavigationResponse, decisionHandler:@escaping (WKNavigationResponsePolicy) -> Swift.Void)

    主机地址被重新定位时触发

    optional public func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!)

2、下面的个方法分别用来追踪加载过程:

       页面开始加载

    optional public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!)

 页面加载失败

    optionalpublicfunc webView(_ webView:WKWebView, didFailProvisionalNavigation navigation:WKNavigation!, withError error: Error)*)

页面提交内容

    optionalpublicfunc webView(_ webView:WKWebView, didCommit navigation:WKNavigation!)

页面完成加载

    optionalpublicfunc webView(_ webView:WKWebView, didFinish navigation:WKNavigation!)

页面加载内容失败

    optionalpublicfunc webView(_ webView:WKWebView, didFail navigation:WKNavigation!, withError error: Error)

    在需要获取证书时*)

    optionalpublicfunc webView(_ webView:WKWebView, didReceive challenge:URLAuthenticationChallenge, completionHandler:@escaping (URLSession.AuthChallengeDisposition,URLCredential?) -> Swift.Void)

    @available(iOS9.0, *)

    optionalpublicfunc webViewWebContentProcessDidTerminate(_ webView:WKWebView)

具体实现和触发时机代码注释中有详细使用:

//MARK: - WKNavigationDelegate
    /**
     执行层级:①
     webView发起请求之前调用
     allow后才会进行后面的代理方法
     decisionHandler 必须执行
     - parameter webView:          响应webView
     - parameter navigationAction: 包含响应事件的信息对象
     - parameter decisionHandler:  回调block,参数:allow or cancel
     */
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
       
        decisionHandler(.allow)
    }
    /**
     执行层级:③
     URL响应正确,接收到相应数据后,决定是否跳转
     decisionHandler 必须执行
     - parameter webView:            响应webView
     - parameter navigationResponse: 请求地址
     - parameter decisionHandler:    回调block,参数:allow or cancel
     */
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
        decisionHandler(WKNavigationResponsePolicy.allow)
        
    }
    /**
     执行层级:②
     允许请求后开始
     
     - parameter webView:    响应webView
     - parameter navigation: navigation
     */
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
    }
    /**
     主机地址被重定向时调用
     
     - parameter webView:    webView description
     - parameter navigation: navigation description
     */
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
    }
    /**
     执行层级:④
     页面加载失败时调用
     
     - parameter webView:    响应webView
     - parameter navigation: navigation
     - parameter error:      error
     */
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        debugPrint(#function + "\nerror: \(error.localizedDescription)")
    }
    /**
     执行层级:④
     当内容开始返回时调用
     
     - parameter webView:    webView description
     - parameter navigation: navigation description
     */
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
        
    }
    /**
     执行层级:⑤
     内容接受完毕后(JS等执行完毕后,在此之前执行 WKUIDelegate 的对应方法)
     
     - parameter webView:    webView
     - parameter navigation: navigation
     */
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        self.webPlaceholderView.addSubview(self.webView)
        self.navigationItem.title = webView.title;
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
        self.webView.evaluateJavaScript("myFunction()") { (object, error) in
            
        }
    }
    /**
     跳转失败时调用
     
     - parameter webView:    webView description
     - parameter navigation: navigation description
     - parameter error:      error description
     */
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
        
    }
    /**
     在访问资源的时候,如果服务器返回需要授权(提供一个NSURLCredential对象)
     
     - parameter webView:           webView description
     - parameter challenge:         challenge description
     - parameter completionHandler:   completionHandler description
     */
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        
        debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
        
        // 认证服务器证书
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            debugPrint("获得服务端证书认证!")
            completionHandler(.performDefaultHandling, nil)
            /*
             /*
                将服务端证书与本地证书对比
             */
            completionHandler(.performDefaultHandling, nil)
            let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
            let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
            let remoteCertificateData
                = CFBridgingRetain(SecCertificateCopyData(certificate))!
            let cerPath = Bundle.main.path(forResource: "tomcat", ofType: "cer")!
            let localCertificateData = NSData(contentsOfFile:cerPath)!
            // 对比证书
            if (remoteCertificateData.isEqual(to: localCertificateData as Data) == true) {
             // 将客户端证书返回给服务端
                let credential = URLCredential.init(trust: serverTrust)
                challenge.sender?.use(credential,
                                      for: challenge)
                completionHandler(.useCredential,
                                  URLCredential.init(trust: challenge.protectionSpace.serverTrust!))
                
            } else {
             // 认证不通过取消请求
                completionHandler(.cancelAuthenticationChallenge, nil)
            }
             */
        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate{
            debugPrint("客户端证书认证!")
            //获取客户端证书相关信息
            
            completionHandler(.useCredential, nil);
        }else {
            debugPrint("其它情况(不接受认证)")
            completionHandler(.cancelAuthenticationChallenge, nil);
        }
        
    }
    /**
     9.0 later,web内容处理中断时会触发
     
     - parameter webView: webView description
     */
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
       debugPrint("class: \(object_getClassName(self))" + #function + "LINE: \(#line)")
    }
           

链接: 1.对于WKWebView的整理: 具体使用

          2.WKUIDelegate:具体使用

具体使用的Demon(持续更新中):Demon(持续更新中)