4

I'm trying to pass a function reference from JavaScript in a WebView, so my Objective-C code can call then back into that function when the asynchronous Obj-C method completes. I see how to pass in simple types -- strings, numbers, etc. -- but can't seem to figure out how to pass something a function reference, like

window.myRootObject.myObjCSelector("some-string", function(data) { 
  console.log(data); 
});

I've Googled around, but continue to come up short, and haven't found a reference to this in the docs (yet). Working in Cocoa, but would love to be able to do the same sort of thing on iOS.

Thanks in advance for any help!

Edit: The function argument should be anonymous -- hopefully this clarifies. :)

2 Answers 2

15

Finally figured this out. There might be a better way (and if so, please chime in!) but the following seems to work. In my Obj-C (NSObject-derived) class -- into which I pass a reference to a WebView -- I define the following script-accessible method:

#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>

- (void) search:(NSString *)prefix withCallback:(WebScriptObject *)callback;

... which is intended to take two arguments: a string to search with, and an anonymous function callback to handle the result. It's implemented thusly:

- (void) search:(NSString *)prefix withCallback:(WebScriptObject *)callback
{
  // Functions get passed in as WebScriptObjects, which give you access to the function as a JSObject
  JSObjectRef ref = [callback JSObject];

  // Through WebView, you can get to the JS globalContext
  JSContextRef ctx = [[view mainFrame] globalContext];

  // In my case, I have a JSON string I want to pass back into the page as a JavaScript object
  JSValueRef obj = JSValueMakeFromJSONString(ctx, JSStringCreateWithCFString((__bridge CFStringRef)responseString)); 

  // And here's where I call the callback and pass in the JS object
  JSObjectCallAsFunction(ctx, ref, NULL, 1, &obj, NULL);
}

This actually works asynchronously as well, through Objective-C blocks, but the gist is above. Hope it helps someone else!

Sign up to request clarification or add additional context in comments.

Comments

0

Maybe if it's a global non-anonymous function you can try passing the function name to Obj-C and then evaluating sth like [NSString stringWithFormat:@"%@()", function_name] ?

4 Comments

Ah, my bad -- it should be anonymous, apologies and I've edited to make that clearer.
I'm afraid this is not possible. Can't you give it some name and use window.myRootObject.myObjCSelector("some-string", mynamespace_func1); ? You could then easily call it from Obj-C...
Sure, I could do that. But how would Objective-C know what JavaScript function to invoke on the WebView, assuming the second argument is a JavaScript function reference? (I hope I'm being clear -- apologies if I'm not.)
I guess it would just look for a function with the given name if you mean that? That's why I think it should be declared as global and not in an inner block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.