WKWebView function for detecting if the URL has changed
Asked Answered
L

3

23

Is there a function for the WKWebView class that allows you to detect whenever the URL of that WebView has changed?

The didCommit and didStartProvisionalNavigation functions don't always seem to fire when working with certain elements within the WebView.

EDIT: Attempted adding a Notification observer. Here's what I have thus far:

extension Notification.Name {
    static let checkURL = Notification.Name("checkURL")
}

NotificationCenter.default.post(name: .checkURL, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(getter: webView.url), name: .checkURL, object: webView.url)
Limes answered 18/12, 2016 at 21:41 Comment(1)
are you using hash navigation?Exceptive
L
15

What do you mean they don't always seem to fire? What kind of elements? They have to in order for the WkWebView to work.

Your first indication that the URL is trying to change is in: decidePolicyForNavigationAction

- (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (WKNavigationAction *) navigationAction decisionHandler: (void (^)(WKNavigationActionPolicy)) decisionHandler {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    decisionHandler(WKNavigationActionPolicyAllow); //Always allow
    NSURL *u1 = webView.URL;
    NSURL *u2 = navigationAction.request.URL; //If changing URLs this one will be different
}

By the time you get to: didStartProvisionalNavigation It has changed.

- (void) webView: (WKWebView *) webView didStartProvisionalNavigation: (WKNavigation *) navigation {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    NSURL *u1 = webView.URL;  //By this time it's changed
}

All you'd have to do is implement these delegate methods (in Swift) and do what you want when you see it change.

Lighterman answered 6/1, 2017 at 22:13 Comment(4)
I apologize for the late reply, but this worked perfectly! Thank you very much!Limes
what is "PRETTY_FUNCTION"? I'm not familiar with it. Also, Matt - do you have the swift code that worked perfectly? I'm having trouble converting this to swift 4Layard
@Layard It's a special identifier originally from C++ used to retrieve, and in this case print, the name of the function that encloses it. Pretty cool feature for logging purposes. Here's an explanation with a little more detail.Boiardo
decidePoliceForNavigationAction is skipped depending on contextGigantes
F
35

Swift Version

// Add observer
webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)

// Observe value
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if let key = change?[NSKeyValueChangeKey.newKey] {
        print("observeValue \(key)") // url value
    }
}
Footrest answered 12/12, 2019 at 6:59 Comment(2)
Thank for your suggestion. :) I lost a lot of time about it.Indigence
But I have a question. How to know what exactly value assign to 'forKeyPath' to get event fire on observeValue func?Indigence
L
15

What do you mean they don't always seem to fire? What kind of elements? They have to in order for the WkWebView to work.

Your first indication that the URL is trying to change is in: decidePolicyForNavigationAction

- (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (WKNavigationAction *) navigationAction decisionHandler: (void (^)(WKNavigationActionPolicy)) decisionHandler {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    decisionHandler(WKNavigationActionPolicyAllow); //Always allow
    NSURL *u1 = webView.URL;
    NSURL *u2 = navigationAction.request.URL; //If changing URLs this one will be different
}

By the time you get to: didStartProvisionalNavigation It has changed.

- (void) webView: (WKWebView *) webView didStartProvisionalNavigation: (WKNavigation *) navigation {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    NSURL *u1 = webView.URL;  //By this time it's changed
}

All you'd have to do is implement these delegate methods (in Swift) and do what you want when you see it change.

Lighterman answered 6/1, 2017 at 22:13 Comment(4)
I apologize for the late reply, but this worked perfectly! Thank you very much!Limes
what is "PRETTY_FUNCTION"? I'm not familiar with it. Also, Matt - do you have the swift code that worked perfectly? I'm having trouble converting this to swift 4Layard
@Layard It's a special identifier originally from C++ used to retrieve, and in this case print, the name of the function that encloses it. Pretty cool feature for logging purposes. Here's an explanation with a little more detail.Boiardo
decidePoliceForNavigationAction is skipped depending on contextGigantes
G
4

You may add an observer:

[webView_ addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew context:NULL];

and the corresponding method that gets called when the URL changes:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context

Glidewell answered 27/12, 2016 at 9:57 Comment(1)
Would you happen to know how to implement using Swift? I created a Notification and added it to my original post. The Notification syntax in Swift is fairly different and I have exhausted all of the possible attempts that I am capable of. I don't know where to go from here.Limes

© 2022 - 2024 — McMap. All rights reserved.