简体   繁体   中英

How can I “catch” the back and forward requests made to UIWebView programmatically?

Javascript calls like these:

history.goBack();
history.goForward();
history.go(-1);

Make the UIWebView go backwards or forwards programmatically. I need a way to know where the user is going before that happens. You may say that the solution is listening to the delegate but there's no such thing as legitimate responses when it comes UIWebView.

This delegate method is called when the user clicks "back" inside a page:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

It's navigationType however is set to LinkClicked and not BackForward as we expected. I have seen enough craziness from UIWebView to be surprised even by a little bit, but it's a dead-end type of problem for me.

I have two propositions:

  1. Create a custom javascript method "myWayOfGoingBack();" and override all goBack(); methods so when it's clicked my method informs me of what is going to happen.
  2. Add a listener to the methods above but I don't really know how javascript works.

Any ideas?

I know that history based events and information are unavailable to JavaScript because they want to prevent privacy leaks. So you can tell the browser what to do with JavaScript in terms of forward/back, but you can't know if it can actually go forward or back.

If you are in control of the HTML inside the WebView as well you could try to pursue 1. People seem to have some succes with it .

I'm a little confused by what you're asking. You've got a UIWebView that you're using to show the user a website, and this website has clickable back and forward buttons/links built in? Is that right? Is this a website that you control, or are you sending them to a third party site?

And regardless, you would like to know what page the WebView is going to load before it loads. Is that right?

The problem is that (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType) has no back/forward navigation type built in. If you wanted, you could keep a global array of every page they visit (update it within the webview: function), and then compare any new request to that list to see if they're visiting pages again. Or you can inject JS to override the link functionality within the javascript

NSString* js = @"function reportBackToObjectiveC(string){var iframe = document.createElement('iframe');iframe.setAttribute('src', 'callback://' + string);document.documentElement.appendChild(iframe);iframe.parentNode.removeChild(iframe);iframe = null;}var links = document.getElementsByTagName('a');for (var i=0; i<links.length; i++) {links[i].addEventListener('click', function() {reportBackToObjectiveC('SOMETHING_HAPPENED');}, true);}";
[WebView stringByEvaluatingJavaScriptFromString:js];

(Sorry that doesn't all fit on the screen, it's compressed to make it injectable. You can copy and paste it out and expand it a bit to see what's actually going on).

That will add an event listener to every link that fires a request to the URL callback://SOMETHING_HAPPENED whenever the user clicks on a link. You can then filter for those sorts of requests within your delegate, and act on them accordingly.

Does that help? Or am I missing the question?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM