32

Is there a way to get the FULL URL loaded by a WKWebView for every request?

webView:didFinishNavigation:

Works only for mainFrame navigations and does not provide a URL request parameter.

How do I get the FULL URL just like in UIWebViewDelegate's

webViewDidFinishLoad:webView

...which gets invoked after any loading finishes and you can get the full request URL from the webView parameter.

It's nice that WKWebView's URL property saves the work that needs to be done to extract a UI-friendly base URL, but it's a huge loss we can't get the full one!

I have tried using

webView:decidePolicyForNavigationAction:decisionHandler:

...but it produces different results for URLs compared to what a UIWebView's request property holds after finishing the load of a page.

Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
i-konov
  • 842
  • 1
  • 7
  • 19
  • Would you not use the `WKNavigationDelegate` for this by looking at the `webView`s request for each request in something like `webView:didStartProvisionalNavigation:`? https://developer.apple.com/library/IOs/documentation/WebKit/Reference/WKNavigationDelegate_Ref/index.html#//apple_ref/occ/intfm/WKNavigationDelegate/webView:didStartProvisionalNavigation: – Popeye Oct 13 '14 at 14:42
  • WKWebView does not have "request" property like UIWebView. Or is there any way to get the request from the WKNavigation object? – i-konov Oct 13 '14 at 14:54
  • Well, the WKNavigationAction does have a request property of type NSURLRequest – leviathan Nov 27 '15 at 11:29
  • It is not always what you might need. Read further on the discussion and you can find out why. I guess I marked this question as answered anywya – i-konov Nov 27 '15 at 11:44

3 Answers3

25

You can get URL for a newly requested Webpage by "navigationAction.request.URL" in decidePolicyForNavigationAction delegate method.

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
   if let urlStr = navigationAction.request.URL?.absoluteString{
      //urlStr is what you want, I guess.
   }
   decisionHandler(.Allow)
}
Yuichi Kato
  • 863
  • 7
  • 16
23

First, I think you are confusing NSURL and NSURLRequest. The first is readily accessibly via webView.URL and it does actually give you the full URL of whatever was loaded. Assuming that where you say URL you mean NSURL.

If that is not what you meant, for example if you wanted to see the redirect chain or the response headers, then I'm afraid the answer is that you cannot get to tht specific information via the WKWebView.

You will have to fall back to UIWebView where you can intercept requests relatively easily and see the full request/response.

Stefan Arentz
  • 34,311
  • 8
  • 67
  • 88
  • Thank you a lot Stefan for your will to help but think you have not understood my case or WKWebView class. The webView.URL gives you - This is the URL that should be reflected in the user interface. This is UI friendly URL string that does not include path, query and so on. By FULL I mean't the URL including all it's parts i.e. the one that come from an automatically generated request when interacting with the web page loaded in the web view. I found a way to get to this using the new navigation delegate protocol. WKWebView is a lot better than UIWebView and I encourage you to get deeper in it – i-konov Mar 12 '15 at 20:37
  • I still don't understand what you mean with *full* URL. I'm printing the `webView.URL` as a test and I see it has all the bits in there, the path, the query, the fragment, etc. I am curious what information are you missing? – Stefan Arentz Mar 12 '15 at 21:39
  • Also note that `webView.URL` has nothing to do with the user interface. It is *not* a UI friendly String, instead It is a ful `NSURL` instance that reflects the page that is currently loaded in the `WKWebView`. – Stefan Arentz Mar 12 '15 at 22:18
  • 2
    Well my bad! I did some research and tests today and the problem seems to be that WKWebView does not report finish of loading on non main frames. You can get request URLs from the decide methods of the navigation delegate but what they redirect to ...you gotta go deeper with URL protocols or you can go with JavaScript evaluations of the the window object. The root of my problem was that I needed all the elements of the loaded URL but it only showed things like youtube.com for example. No watch?v= and so on. – i-konov Mar 13 '15 at 19:39
  • So i will mark your answer as correct but people should look at my previous comment for a detailed situation on what goes on with URLs when working with WKWebView. – i-konov Mar 13 '15 at 19:44
  • 1
    There are many questions here about using `NSURLProtocol` in combination with `WKWebView`. Unfortunately because the network calls happen in a separate sandboxed process, you cannot use that trick anymore. If you need that level of access to requests that the web view is making then your only option is to use `UIWebView` instead. – Stefan Arentz Mar 13 '15 at 19:46
13

This is Yuichi Kato's answer for Swift 4. It retrieves the full URL from the request property of the navigation action in the webView(_:decidePolicyFor:decisionHandler:) method of WKNavigationDelegate.

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if let urlStr = navigationAction.request.url?.absoluteString {
        //urlStr is what you want
    }

    decisionHandler(.allow)
}

Don't forget to conform your class to WKNavigationDelegate and set your web view's delegate accordingly:

class WebViewController: UIViewController, WKNavigationDelegate

[...]

webView.navigationDelegate = self
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223