UIWebView communication to Objective-C (without JavaScript)

CansUIWebViews allow for rich content presentation within your iOS application. A bit of CSS, some images, and control over the font display means your applications can look much, much better in places.

Depending on the content, you might be able to mirror the content online if you’d like as well outside of the application – the content serves double-duty.

I recently had a situation where a main content area was being displayed in a UIWebView… pages of content. The user could use a UITableView to select the page they wanted to display in the web control. Easy enough.

However the content needed links within it that would jump to other pages as well – as typical web pages do… but these links needed to be intercepted and my own logic applied to them.

If you’ve ever wanted to call an Objective-C method from links in a UIWebView and you weren’t quite sure how to go about the business, this post will show you the light. In order to set this up, make sure that your viewController hosting the UIWebView has a UIWebView delegate assigned <UIWebViewDelegate>. In my case in my .h, it looks like this (lines of code artificially shortened to display better in the allotted space here):

@interface DetailViewController :
    UIViewController <UISplitViewControllerDelegate,
    UIWebViewDelegate> {

Now, you’ll want to evaluate the link destination. To do this, because of the delegate, a callback method will be called upon touching a link in your HTML page loaded into the UIWebView. To do this, simply add the following method to your viewController class:

- (BOOL)webView:(UIWebView *)webView
    shouldStartLoadWithRequest:(NSURLRequest *)request 
    navigationType:(UIWebViewNavigationType)navigationType {
    //logic to come
    NSLog(@"link pressed");
    return YES;
}

Test it out in your project – you’ll get that log statement regardless. Once you have that working, it’s time to set up a custom URL scheme in your HTML and then evaluate what’s being called in the delegate callback. In this way you’re creating your own functionality for links in your HTML. Perfect. Remember, normally formatted links will behave as they should… but if you wanted to prevent all links in your HTML to load content, you could always use the delegate method to return NO for all links – preventing linking for taking place.

In your HTML set up a test link. Set a custom prefix for the url. You can use what you’d like to, but I find using “myApp://” works nicely. So your HTML link may look like this:

<a href="myApp://section=2&page=5">Test Link</a>

The URL will be inspected in the delegate method within your viewController. I’ll show you that next. Let’s add functionality…

- (BOOL)webView:(UIWebView *)webView
    shouldStartLoadWithRequest:(NSURLRequest *)request
    navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = [[request URL] absoluteString];
    static NSString *urlPrefix = @"myApp://";
    if([url hasPrefix:urlPrefix]){

        NSString *paramsString = [url substringFromIndex:[urlPrefix length]];
        NSArray *paramsArray = [paramsString componentsSeparatedByString:@"&"];
        int paramsAmount = [paramsArray count];

        NSString *section;
        NSString *page;

        for (int i = 0; i < paramsAmount; i++) {
            NSArray *keyValuePair = [[paramsArray objectAtIndex:i] componentsSeparatedByString:@"="];
            NSString *key = [keyValuePair objectAtIndex:0];
            NSString *value = nil;
            if ([keyValuePair count] > 1) {
                value = [keyValuePair objectAtIndex:1];
            }

            //Assign these values.
            if([key isEqualToString:@"section"]){
                section = value;
            } else if([key isEqualToString:@"page"]){
                page = value;
            }            

            if (key && [key length] > 0) {
                if (value && [value length] > 0) {
                    if ([key isEqualToString:@"page"]) {
                        // Use the page...
                    }
                }
            }
        }
        NSString *destinationURL = [NSString stringWithFormat:@"page%@_%@.html", section, page];
        NSLog(@"%@", destinationURL);
        return NO;
    } else {
        return YES;
    }
}

This code performs no error checking – it assumes that you’ve used the custom prefix with the proper formatting. You’ll want to code in checks for that on your own. Anyway – going through the code, you can see how the URL is broken apart and the pieces used to construct a NSString for a URL here – in anticipation to use it to load in the proper page into the UIWebView.

So this is a good primer in rolling this out on your own. If you have questions or improvements for this, please feel free to leave a comment for this post. Enjoy!

Related Posts Plugin for WordPress, Blogger...

4 thoughts on “UIWebView communication to Objective-C (without JavaScript)

  1. José Antonio

    Hello, congratulations for this post, casually I need to do something like this, but I’m just starting to develop for iOS environment, so Would you mind to add a link to download the example code? I’d appreciate a lot. Thank you

    Reply
  2. pdschullerDotCom

    ‘pretty sure there’s a little detail that’s missing – tho it probably only is a problem for a complete newb (like me).

    In – (void)viewDidLoad for the ViewController that houses the UIWebView, you have to tell it that it is its own delegate.

    the instance of my UIWebView is named my_web_view, so I used this:

    my_web_view.delegate = self;

    awesome post tho. Thanks tons.

    Reply
  3. Jyotsna Kadam

    Best solution… It work for me.. You save me boss….Thank you very much for posting useful solution..

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


7 − five =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>