I have part of my app written in JS and running inside of a WebView. I'm using the UIWebView shouldStartLoadWithRequest method to capture http requests as a means of communicating between JS and obj-c. This works great until I attempt to load a Modal View Controller over my webview from inside the shouldStartLoadWithRequest method. Once this happens, shouldStartLoadWithRequest is no longer called. Sometimes I need to dismiss this modal view controller and go back to the webview and do some things and then re-present the modal controller. The modal controller comes up the first time just fine, then I dismiss it and attempt to present it again by navigating to a URL from javascript and it no longer will present itself. NSLogs inside shouldStartLoadWithRequest are never run.
In my javascript I do something like this:
window.location='myapp:whateverMethod';
objective c code looks like this:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[request URL] absoluteString];
NSLog(@"REQUEST URL: %@", requestString);
if([requestString hasPrefix:@"myapp:"]) {
NSArray *components = [requestString componentsSeparatedByString:@":"];
NSString *function = [components objectAtIndex:1];
if([self respondsToSelector:NSSelectorFromString(function)]) {
[self performSelector:NSSelectorFromString(function)];
}
return NO;
}
return YES;
}
-(void) whateverMethod {
NSLog(@"whateverMethod called!");
// This is a quick way to grab my view controller from the storyboard, so assume it exists
UIViewController *splash = [self.storyboard instantiateViewControllerWithIdentifier:@"splashViewController"];
[self presentModalViewController:splash animated:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self dismissModalViewController:splash animated:NO];
});
}
At this point my webview is still visible. I navigate from page to page in my webapp and all javascript works great in it but the "shouldStartLoadWithRequest" delegate method of the webview no longer is called. I cannot figure out why. Does anyone have any ideas?
Checked out Cordova and they have their own queuing system, not really a help. But...
Disobedient Media's answer gave me an idea. Instead of window.location, why not try window.location.hash.
Now some JS code for logging is:
and the Objective-C code is:
You get the full URL including 'http:...' so I chose tilde instead of colon, and incremented the indices. Now you can log all willy-nilly and send whatever amount of commands you want and they will all get through :-)
I noticed that Cordova doesn't set the window.location property. Instead it has two options: it either creates an iframe and sets the src of the iframe to that url, or it creates an XMLHttpRequest object e.g. in the iOSExec() function:
That being said, it may be beneficial to use something like Cordova instead of trying to roll it yourself (even if it's just embedding their view controller), since they handle a lot of the headaches that come up with webview delegates.
I've just had the same problem, but related to using a href="#" anchor.
This Stack Overflow answer sorted it
There are more answers on that thread that deal with widow.location, so you may have luck with them.
I (embarrassingly) spent a couple of hours working on this today, and realised that in my viewDidDisappear: I was setting the UIWebViewDelegate to nil!
All I needed to do to fix was once the modal was dismissed, re-set the UIWebViewDelegate and everything worked again.