javascriptiosjavascriptcore

Call native objective methods from JavaScript using JavaScript core framework


Suppose I have three classes.

  1. A view controller with a button present on it.
  2. JavaScript file with some JavaScript methods.
  3. Model objective class with some methods of calling web-service.

When I press button on view controller, it calls .js (JavaScript file) and in return .js file calls methods from model class.

I just want to know if it is possible using JavaScript core framework without using web view.


Solution

  • The Objective-C interface in the JavascriptCore framework introduced with iOS 7 / OS X 10.9 permits calling Objective-C methods from Javascript and calling Javascript functions from Objective-C. Both of these scenarios can occur without involving a webview. For a great intro to these features, check out the 2013 WWDC introduction "Integrating JavaScript into Native Apps" session on Apple's developer network: https://developer.apple.com/videos/wwdc/2013/?id=615

    Below is a simple example. You can also create more sophisticated examples that directly expose existing methods via the JSExport protocol (see the pdf/video above).

    myJavascript.js:

    function myJavascriptFn(arg) {
        myObjC_callback(arg); // Call Objective C code
    }
    

    myView.m:

    #import <JavaScriptCore/JavaScriptCore.h>
    
    ....
    
    javascriptContext  = [[JSContext alloc] init]; // Create a standalone javascript VM and context.
    
    // Load the javascript file into the VM
    NSURL *scriptURL = [NSURL URLWithString:@"path/to/myJavascript.js"];
    NSError *error = nil;
    NSString *script = [NSString stringWithContentsOfURL:scriptURL encoding:NSUTF8StringEncoding error:&error];
    [javascriptContext evaluateScript:script];
    
    // Set up calling an Objective-C callback for Javascript to use
    javascriptContext[@"myObjC_callback"] = ^(NSString *arg) {
        NSLog(@"Calling someObjectiveCMethod from javascript.  Passed arg is:%@", arg);
        [self someObjectiveCMethod:arg];
    }
    
    // Call javascript from Objective C
    JSValue *myJavascript_callback = javascriptContext[@"myJavascriptFn"];
    [myJavascript_callback callWithArguments:@[@"test arg"]];
    

    The JavascriptCore framework also provides built-in conversion between common Objective-C types and Javascript types. See my answer to How is an ObjC JS bridge translated? for more details.