5

JavascriptCore is a new framework supported in iOS7. We can use the JSExport protocol to expose parts of objc class to JavaScript.

In javascript, I tried to pass function as parameter. Just like this:

function getJsonCallback(json) {
        movie = JSON.parse(json)
        renderTemplate()
}
viewController.getJsonWithURLCallback("", getJsonCallback)

In my objc viewController, I defined my protocol:

@protocol FetchJsonForJS <JSExport>
 - (void)getJsonWithURL:(NSString *)URL
               callback:(void (^)(NSString *json))callback;
 - (void)getJsonWithURL:(NSString *)URL
         callbackScript:(NSString *)script;
@end

In javascript, viewController.getJsonWithURLCallbackScript works, however, viewController.getJsonWithURLCallback not work.

Is there any mistake that I used block in JSExport? Thx.

1 Answer 1

7

The problem is you have defined the callback as an Objective-C block taking a NSString arg but javascript doesn't know what to do with this and produces an exception when you try to evaluate viewController.getJsonWithURLCallback("", getJsonCallback) - it thinks the type of the second parameter is 'undefined'

Instead you need to define the callback as a javascript function.

You can do this in Objective-C simply using JSValue.

For other readers out there, here's a complete working example (with exception handling):

TestHarnessViewController.h:

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

@protocol TestHarnessViewControllerExports <JSExport>
- (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback;
@end

@interface TestHarnessViewController : UIViewController <TestHarnessViewControllerExports>
@end

TestHarnessViewController.m: (if using copy/paste, remove the newlines inside the evaluateScript - these were added for clarity):

#import "TestHarnessViewController.h"

@implementation TestHarnessViewController {
    JSContext *javascriptContext;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    javascriptContext  = [[JSContext alloc] init];
    javascriptContext[@"consoleLog"] = ^(NSString *message) {
        NSLog(@"Javascript log: %@",message);
    };
    javascriptContext[@"viewController"] = self;

    javascriptContext.exception = nil;
    [javascriptContext evaluateScript:@"
        function getJsonCallback(json) {
            consoleLog(\"getJsonCallback(\"+json+\") invoked.\");
            /* 
            movie = JSON.parse(json); 
            renderTemplate(); 
            */
        } 

        viewController.getJsonWithURLCallback(\"\", getJsonCallback);
    "];
    JSValue *e = javascriptContext.exception;
    if (e != nil && ![e isNull])
        NSLog(@"Javascript exception occurred %@", [e toString]);
}

- (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback {
    NSString *json = @""; // Put JSON extract from URL here
    [callback callWithArguments:@[json]];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

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

5 Comments

do getJsonWithURLCallback(\"\", getJsonCallback) in javascript calls - (void)getJsonWithURL:(NSString *)URL callback:(JSValue *)callback ? I was having issue fro calling two parameterized function from javascript using JSContext please help.
@jnix - sorry I didn't understand your comment. Perhaps you should post a new question.
@Mike I was saying I was unable to call native objcC function with to parameters .For more detail you can see -stackoverflow.com/questions/22801909/… quetion
@jnix - Your comment above didn't explain what problem you were running into (especially since the sample answer already worked for two parameters), but reading your other question I see you've already solved it - ObjC methods exposed via JSExport have altered names if multiple parameters are involved objCMethod:withArgTwo:andArgThree: becomes objCMethodWithArgTwoAndArgThree() in javascript.
It its true. I came to know after trying combinations:D thanks for replying.

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.