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.
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:
- javascript injection to capture the page changes (read up on history.pushState).
- KVO to watch for changes to the webview (like the scrollview resizing)
- watching for the title change, as above.
- checking for updates every time the user taps the view.
Use whichever one makes sense for your needs.
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
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.