2

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.

OdieO
  • 6,836
  • 7
  • 56
  • 88

3 Answers3

4

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.

jimejim
  • 594
  • 6
  • 8
  • I'm sure that's not the best solution, but it worked for me. Thanks a lot! – serg_ov Aug 23 '14 at 19:19
  • 1
    See my update above. Some of the other solutions can work more reliably, I think. I've noticed sometimes the timer can get a little confused if the connection is slow or other things are going on. – jimejim Aug 30 '14 at 16:11
0

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

Community
  • 1
  • 1
Hunter Mitchell
  • 7,063
  • 18
  • 69
  • 116
  • Pretty sure this isn't the issue. The `UIWebView` exists upon initial load of the site and the delegate methods are being called. Once, again, it's listening to link clicks in a couple other sites I tried (`nba.com` and `vimeo.com`) but clicking a link in `m.youtube.com` isn't captured. – OdieO Feb 01 '14 at 21:30
  • @SmoothAlmonds Alright, this might be something to do will youtube's web programming. I will continue to look for the answer – Hunter Mitchell Feb 01 '14 at 21:31
  • Yeah, I pretty sure that's it. It's on purpose to prevent exactly what I'm doing?... The other option to achieve what is to use their `Data API` and create a simple version of a `youtubeSearchVC`, which we'll probably do anyway.... We just wanted the simplest implementation for initial testing. – OdieO Feb 01 '14 at 23:32
0

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.

Community
  • 1
  • 1
  • Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. Don't just put in the links but instead include the steps yourself. – Ali Bdeir Oct 20 '16 at 17:54