WKWebView on iOS: how can I intercept a click and get related content?

In WKWebView , when a user clicks on a link related to certain types of files (for example, a VCF file for contacts or an ICS file for calendar events), I would like to intercept the link, that is, cancel the navigation and instead display the contents using a specialized view controller.

For example, CNContactViewController can be used to display contacts, EKEventViewController can be used to display calendar events.

I can intercept the click by assigning WKNavigationDelegate and using 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) } } } 

But in order to display files of specialized controllers, I need to first load data from a given url .

How can i do this?

Because authentication is required for the download, downloading requires sharing cookies using WKWebView or using another method to share an already authenticated session.

If this helps: I already have access to the WKProcessPool and WKWebViewConfiguration . As far as I understand, cookies are somehow tied to WKProcessPool . But I do not know how to use this to load content, for example using NSURLSession .

+5
source share
1 answer

It feels hacky, but I solved it by doing a WKWebView execution of some javascript that fetches the contents via ajax and returns it to completionHandler in swift.

Background

WKWebView supports the evaluateJavaScript call, which passes the javascript result to completionHandler :

 func evaluateJavaScript(_ javaScriptString: String, completionHandler completionHandler: ((AnyObject?, NSError?) -> Void)?) 

Since there is jQuery on the server side, I used this to send ajax , as shown below. But of course this can be done using javascript .

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

url can be passed in javascript with fast string interpolation .

Extend WKWebView

To easily use this, I have expanded the WKWebView class.

 // 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) }) } } 

Using

From an example question, this can be called as follows:

 let url = navigationAction.request.URL! if url.pathExtension == "ics" { decisionHandler(WKNavigationActionPolicy.Cancel) webView.readUrlContent(url) { (result: String) in print(result) // TODO: display with EKEventViewController } } 
+1
source

All Articles