Calling UIWebView from JavaScript

you think you’re soooo smart making a responsive site that gets loaded into a webview so you can say you made a native app…clever. until you realize you have to set some settings and need a pipeline between javascript and objective-c!

This will help you out. There are a couple libraries out there:

From JavaScript to Objective-C

if you’re looking for something small/easy you do this:

  1. make your own protocol (instead of http:// you would use mike://)
  2. make a url request, which ultimately is an event you can look for with UIWebView
  3. process the request in UIWebView and handle any items from your scheme accordingly

So on the JavaScript side:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

function execute(url) {
                       var iframe = document.createElement("iframe");
                       iframe.setAttribute("src", url);
                       document.documentElement.appendChild(iframe);
                       iframe.parentNode.removeChild(iframe);
                       iframe = null;
                   }
                               
                   execute('mike://this/is/a/custom/function');

[/pastacode]

and on the objective-c side:

[pastacode lang=”c” message=”” highlight=”” provider=”manual”]

- (BOOL) webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *URL = [request URL];
    if ([[URL scheme] isEqualToString:@"mike"]) {
        // parse the rest of the URL object and execute functions
        NSLog(@"received url with scheme: %@", [URL scheme]);
    }
    return YES;
}

// also make sure you've implemented the delegate method ViewController.h
@interface ViewController : UIViewController <UIWebViewDelegate>

// and in ViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [webView setDelegate:self];
}

[/pastacode]

The reason you use iframes instead of “window.location” is because there are limits to how fast you can call window.location. However, if you load iframes and dump the objects out of the document after creation, it negates the url request limit. There are similar hacks all over dealing with ddos attacks that use a similar approach, and in this case allows you to call objective c much more often.

Also, props to this guy.

From Objective-C to JavaScript

So for this you can actually execute functions and shit from objective-c. You just need to make sure the function calls are in the right scope, so if you have something defined in window it would just be:

[pastacode lang=”c” message=”” highlight=”” provider=”manual”]

[webView stringByEvaluatingJavaScriptFromString:@"testObjectiveCMethod();"]; 

[/pastacode]

Usually, you will want to execute these functions after the window has had a chance to load so:

[pastacode lang=”c” message=”” highlight=”” provider=”manual”]

// webview finished loading
- (void) webViewDidFinishLoad:(UIWebView *)__webView
{
    //Execute javascript method or pure javascript if needed
    [webView stringByEvaluatingJavaScriptFromString:@"testObjectiveCMethod();"];
}

[/pastacode]

Then on the front end, have an alert or something to show you it worked:

[pastacode lang=”javascript” message=”” highlight=”” provider=”manual”]

<script>
function testObjectiveCMethod() {
                console.log('things and stuff');
                alert('things and stuff');
            }
        </script>

[/pastacode]

That’s all

2 thoughts on “Calling UIWebView from JavaScript

  1. I’m thinking about this “The reason you use iframes instead of “window.location” is because there are limits to how fast you can call window.location.”

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.