iOS中的WKWebView:如何拦截点击并检索链接的内容?

fie*_*edl 5 ios swift wkwebview

在a中WKWebView,当用户单击引用某些文件类型的链接(例如,联系人的VCF文件或日历事件的ICS文件)时,我想截取该链接,即取消导航,而是显示内容使用专门的视图控制器.

例如,CNContactViewController可用于显示联系人,EKEventViewController可用于显示日历事件.

我可以通过分配WKNavigationDelegate和使用来拦截点击decidePolicyForNavigationAction:

// Swift 2
extension MyController: WKNavigationDelegate {
  func webView(webView: WKWebView, decidePolicyForNavigationAction 
      navigationAction: WKNavigationAction, 
      decisionHandler: (WKNavigationActionPolicy) -> ()) {

    let url = navigationAction.request.URL!

    if url.pathExtension == "ics" {
      decisionHandler(WKNavigationActionPolicy.Cancel)
      // TODO: download data
      // TODO: display with EKEventViewController
    } else if url.pathExtension == "vcf" {
      decisionHandler(WKNavigationActionPolicy.Cancel)
      // TODO: download data
      // TODO: display with CNContactViewController
    } else {
      decisionHandler(WKNavigationActionPolicy.Allow)
    }

  }
}
Run Code Online (Sandbox Code Playgroud)

但是为了显示专用控制器的文件,我需要先从给定的数据中下载数据url.

我怎样才能做到这一点?

由于下载需要身份验证,因此下载需要与其共享cookie WKWebView,或使用其他技术来共享已经过身份验证的会话.

如果有帮助:我已经有访问网络视图的WKProcessPoolWKWebViewConfiguration.根据我的理解,cookie与某种程度上有关WKProcessPool.但我不知道如何使用它来下载内容,例如使用NSURLSession.

fie*_*edl 3

这感觉很hacky,但我通过执行WKWebView一些javascript来解决这个问题,该javascript通过ajax检索内容并将其返回到completionHandlerswift中。

背景

支持WKWebView调用evaluateJavaScript,将 javascript 的结果传递给completionHandler

func evaluateJavaScript(_ javaScriptString: String,
    completionHandler completionHandler: ((AnyObject?, NSError?) -> Void)?)
Run Code Online (Sandbox Code Playgroud)

由于服务器端有jQuery ,我用它来发送ajax请求,如下所示。但是,当然,这也可以使用普通的 javascript 来完成

(function(url) {
  var result = '';
  $.ajax({
    type: 'GET',
    url: url, 
    success: function(r) {result = r}, 
    failure: function() {result = null}, 
    async: false
  }); 
  return result 
})(url)
Run Code Online (Sandbox Code Playgroud)

可以通过 swift 的字符串插值url传递给 javascript 。

延长WKWebView

为了轻松使用它,我扩展了该类WKWebView

// Views/WKWebView.swift
import WebKit

extension WKWebView {
  func readUrlContent(url: NSURL, completionHandler: (result: String) -> Void) {

    self.evaluateJavaScript("(function() { var result = ''; $.ajax({type: 'GET', url: '\(url)', success: function(r) {result = r}, failure: function() {result = null}, async: false }); return result })()", completionHandler: { (response, error) -> Void in

      let result = response as! String
      completionHandler(result: result)

    })

  }
}
Run Code Online (Sandbox Code Playgroud)

用法

从问题的示例来看,可以这样调用:

let url = navigationAction.request.URL!
if url.pathExtension == "ics" {
  decisionHandler(WKNavigationActionPolicy.Cancel)
  webView.readUrlContent(url) { (result: String) in
    print(result)
    // TODO: display with EKEventViewController
  }
}
Run Code Online (Sandbox Code Playgroud)