UIWebView not calling shouldStartLoadWithRequest w

2019-04-14 18:55发布

问题:

So this question requires more web knowledge than cocoa knowledge. I know only the basics of web am stumped. This is also a bit of an edge case (although my sample size is small).

I'm playing around with a feature to cross-post videos from youtube into our app.

So I have a browserController and I load http://m.youtube.com and it loads fine. shouldStartLoadWithRequest is called upon initial load. However, if I click a link to go to a video's page shouldStartLoadWithRequest is never called.

I've tried out a couple other sites (nba.com and vimeo.com) and they work as expected, shouldStartLoadWithRequest IS called when a link is clicked, so that leads me to believe there's nothing wrong with my browserController nor my UIWebView code and it's something particular to the way the youtube site is handling it's link clicks.

Any idea what's going on and how to either make sure shouldStartLoadWithRequest is called or else listen to the link click otherwise?

PS. I had no idea how to tag this so that it refers to which web frameworks this might involve.

回答1:

I decided to go a different route and created an NSTimer that periodically grabs the current url using javascript. When it changes, I know the page switched. I disable the timer briefly if shouldStartLoadWithRequest is called. I reenable it on successful load.

It's not perfect, but works well enough for my needs and works on m.youtube.com. I imagine there is some more advanced javascript that could specifically get the link clicks also, but just checking for url updates works ok.

// assume self.currentURL and self.updateTimer exist in controller

// check every 2 seconds
-(void) startTimer {
    [self stopTimer];
    self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:2.0
                                                        target:self
                                                      selector:@selector(timerUpdate)
                                                      userInfo:nil
                                                       repeats:YES];
}

-(void) stopTimer {
    [self.updateTimer invalidate];
    self.updateTimer = nil;
}

-(void) timerUpdate {

    NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    NSString *url = [self.webView stringByEvaluatingJavaScriptFromString:@"document.URL"];

    if (![url isEqualToString:self.currentURL]) {
        NSLog(@"New URL: %@", url);
        self.currentURL = url;
    }

    // update back/forward buttons here 
}

UPDATE: Unfortunately all the solutions for this particular problem right now are a little bit of a hack. This talk gives some other ideas: http://vimeo.com/61488911

Options boil down to:

  1. javascript injection to capture the page changes (read up on history.pushState).
  2. KVO to watch for changes to the webview (like the scrollview resizing)
  3. watching for the title change, as above.
  4. checking for updates every time the user taps the view.

Use whichever one makes sense for your needs.



回答2:

Try the answers in these similar issues:

shouldStartLoadWithRequest is never called

Undeclared delegate and shouldStartLoadWithRequest

And make sure you set your delegate.

webview.delegate = self; 

Also, look here: UIWebView Link Click

In a comment one person stated: Actually it won't always be called. For example, in some m.youtube.com pages.

In multiple question i continueally see that this will not work in m.youtube.com . Like in this post: iPhone - UIWebview - Get the URL of the link clicked



回答3:

http://m.youtube.com processes all the links via AJAX. But shouldStartLoadWithRequest is not called for XHR requests. You need to inject JavaScript code that would reload page (see Knowing when AJAX has loaded in UIWebView for UIWebView) or send messages to native application (see How can i monitor requests on WKWebview? for WkWebView) after each XHR request.