views:

1926

answers:

5

I have a WebView, and I want to call a view in Objective-C from JavaScript. Does someone know how I can do this?

+4  A: 

If you have an object with a method -[MyObject myMethod:(NSString*)v], you can register it with your webview's windowScriptObject like this:

MyObject* myObject = [[MyObject alloc] init];
id win = [webView windowScriptObject];
[win setValue:myObject forKey:@"myObject"];

And then call it from javascript like this:

function myFunction() {
    var myObject = window.myObject;
    var value = myObject.myMethod_(@"hello");
    alert(value);
}

Colons in the Objective-C selector are replaced by underscores in javascript. So a @selector(doSomethingWithThis:andThat:) is translated to doSomethingWithThis_andThat.

nschmidt
Pretty sure that method only exists on the desktop WebView, not the Cocoa Touch UIWebView. Unfortunately!
Sixten Otto
@Sixten Otto: You are right. I missed the cocoa-touch and iphone tag :)
nschmidt
+2  A: 

Assuming you're doing an app, you can look at how PhoneGap implements that (or even use it). It's a library that supports back-and-forth communication between JS and OBJ-C. There are other libraries and solutions, as well.

If you're talking about a web app (something the user gets to from Mobile Safari), you can't get to Objective-C from there.

Nosredna
+11  A: 

The standard workaround for UIWebView is to set a UIWebViewDelegate, and implement the method webView:shouldStartLoadWithRequest:navigationType:. In your JavaScript code, navigate to some fake URL that encodes the information you want to pass to your app, like, say:

window.location = "fake://myApp/something_happened:param1:param2:param3";

In your delegate method, look for these fake URLs, extract the information you need, take whatever action is appropriate, and return NO to cancel the navigation. It's probably best if you defer any lengthy processing using some flavor of performSelector.

Sixten Otto
A: 

I have written that code in my ViewController:

   - (BOOL)webView:(UIWebView *)webView2 
 shouldStartLoadWithRequest:(NSURLRequest *)request 
 navigationType:(UIWebViewNavigationType)navigationType {

 NSString *requestString = [[request URL] absoluteString];
 NSArray *components = [requestString componentsSeparatedByString:@":"];

 if ([components count] > 1 && 
  [(NSString *)[components objectAtIndex:0] isEqualToString:@"myapp"]) {
  if([(NSString *)[components objectAtIndex:1] isEqualToString:@"myfunction"]) 
  {

   NSLog([components objectAtIndex:2]); [[Airship shared] displayStoreFront]; //<- This is the code to open the Store
   NSLog([components objectAtIndex:3]); // param2
   // Call your method in Objective-C method using the above...
  }
  return NO;
 }

 return YES; // Return YES to make sure regular navigation works as expected.
}

And in Javascript:

        function store(event)
{
    document.location = "myapp:" + "myfunction:" + param1 + ":" + param2;
}

But nothing happen....

Obliviux
A: 

Like people said here, you have to use the method webView:shouldStartLoadWithRequest:navigationType: from the UIWebviewDelegate.

This api http://code.google.com/p/jsbridge-to-cocoa/ does it for you. It is very lightweight. You can pass images, strings and arrays from javascript to objective-C.

John