1

I have a simple iOS app with a single view that contains a UIWebView. Within my webView, I display my jQuery Mobile website.

Since jQuery Mobile loads pages via ajax, the webViewDidStartLoad and webViewDidFinishLoad methods are NOT called once the initial page loads. I've found similar questions on SO such as this one, but I'm not sure where to use the window.location = "localFunction" call, and no one has yet to confirm this actually works.

Here's my issue (example):

  1. App Starts
  2. shouldStartLoadWithRequest is called
  3. webViewDidStartLoad is called, and network activity indicator is shown.
  4. webViewDidFinishLoad is called, network activity indicator is hidden, and webView displays the initial web page.
  5. User clicks a link from the homepage
  6. shouldStartLoadWithRequest is called
  7. The second page is displayed, but webViewDidStartLoad and webViewDidFinishLoad are not called again for the duration of the session.

Is there a way to force jQuery Mobile or the iOS app to call webViewDidStartLoad and webViewDidFinishLoad so that I can do a simple task, such as show a network activity indicator when webViewDidStartLoad is called, and hide it when webViewDidFinishLoad is called?

Community
  • 1
  • 1
adamdehaven
  • 5,890
  • 10
  • 61
  • 84

3 Answers3

1

If you want to signal the UIWebView of page changes; you can use the custom-scheme launching option as discussed in the SO post in your question.

Define a window.location change in the pagebeforechange handler: (JQM Page change events)

logToIosConsole: function(msg){ 
    console.log("logToIosConsole: log://"+msg); 
    var standalone = window.navigator.standalone, 
    userAgent = window.navigator.userAgent.toLowerCase(), 
    safari = /safari/.test( userAgent ), 
    ios = /iphone|ipod|ipad/.test( userAgent ); 

    if( ios ) { 
        if ( !standalone && !safari ) { 
            //uiwebview 
            window.location = "log://"+msg; 
        }; 
    } else { 
        //not iOS 
    }; 

Use it in javascript

$(document).on("pagebeforechange", function(eve, ui){
    logToIosConsole("pagebeforechange called on "+eve.currentTarget.URL);
});

Intercept this custom-url-scheme in your shouldStartLoadWithRequest

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *theAnchor=[[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ;
    if([theAnchor hasPrefix:@"log:\/\/"]) {
        NSString *logText=[theAnchor substringFromIndex:@"log:\/\/".length];
        NSLog(@"LogMsg==>%@",logText);
        return NO; 
    }
}
Nirmal Patel
  • 5,128
  • 8
  • 41
  • 52
  • With ajax enabled, the `webViewDidStartLoad` function is still not being called, even with the "mylog" thing. – adamdehaven Jul 24 '12 at 15:04
  • updated with code from my current project where I log to Xcode console from JS... – Nirmal Patel Jul 25 '12 at 12:15
  • Can you give me a quick explanation as to what this will do? (thanks ahead of time) – adamdehaven Jul 25 '12 at 12:32
  • When running inside a UIWebView, all calls to logToIosConsole(msg) from Javascript will log the "msg" to the xCode/iOS console. The log:// acts as a bridge for sending msg from JS to ObjC. – Nirmal Patel Jul 25 '12 at 13:14
  • 1
    I don't think that this will still call the `webViewDidStartLoad` and `webViewDidFinishLoad`. Look at my answer above yours - it seems to be a problem with jQuery Mobile loading pages via Ajax. I really appreciate the help though! – adamdehaven Jul 25 '12 at 13:16
  • You are right. This will not invoke `webViewDid*Load` methods. But what you can do is place a `logToIosConsole` call before and after the actual `changePage` and execute the required ObjC code when intercepting `log://` in `shouldStartLoadWithRequest`. – Nirmal Patel Jul 25 '12 at 13:48
  • I probably won't use this at the moment, but that's good to know! Thanks! – adamdehaven Jul 25 '12 at 13:49
0

webViewDidStartLoad and webViewDidFinishLoad are only invoked when window.location changes. UIWebView cannot intercept Ajax calls.

You can either turn-off JQM's Ajax navigation - globally by setting ajaxEnabled="false" or individual pages/links using data-ajax="false".

OR

If the problem is simply showing an activity indicator; you could use JQM's in-built activity indicator by invoking $.mobile.showPageLoadingMsg.

Nirmal Patel
  • 5,128
  • 8
  • 41
  • 52
  • Thanks for the quick response... My JQM activity indicator is showing, I'm just wanting to call some other things within my app that would be called by the `webViewDidStartLoad` and `webViewDidFinishLoad` methods. So turning off the ajax navigation is the only work-around? I'll try it real quick... – adamdehaven Jul 24 '12 at 13:58
0

It is a problem with the way the jQuery Mobile site renders pages. They DO get called if you disable ajax navigation for the site. With Ajax ENABLED, the webViewDidStartLoad never gets called when clicking a link because since the page is requested through Ajax, the window location doesn't change, and therefore iOS doesn't register a page change or page load.

adamdehaven
  • 5,890
  • 10
  • 61
  • 84