Execute Javascript in iOS Applications

In this tutorial, I have covered How to execute JavaScript in iOS / Objective-C. You can execute JavaScript in iOS applications with the help of JavaScriptCore.framework. This framework is supported in iOS7 & OSX 10.9

List of features supported by Javascript.framework
a) Evaluate JavaScript code in Objective-C
b) Access JavaScript Variables in Objective-C
c) Access JavaScript functions and execute them in Objective-C
d) Execute Objective-C code from JavaScript
e) Export Objective-C classes and use them in JavaScript.

Download the source code: Download source of Execute JavaScript in iOS Application

To access JavaScript framework, you need to include the header file

#import <JavaScriptCore/JavaScriptCore.h>

List of Main Classes supported by framework:
JSContext : For any javascript operations you need JSContext.

         JSContext *context = [[JSContext alloc] init];

JSValue : JSValue holds JavaScript values,variables and functions. List of main methods in JSValue.

	
	// Convert this value to a corresponding Objective-C object, according to the
	// conversion specified above.
	- (id)toObject;

	// Convert this value to a corresponding Objective-C object, if the result is
	// not of the specified class then nil will be returned.
	- (id)toObjectOfClass:(Class)expectedClass;

	// The value is copied to a boolean according to the conversion specified by the
	// JavaScript language.
    - (BOOL)toBool;

    // The value is copied to a number according to the conversion specified by the
    // JavaScript language.
    - (double)toDouble;

    // The value is copied to an integer according to the conversion specified by
    // the JavaScript language.
    - (int32_t)toInt32;

    // The value is copied to an integer according to the conversion specified by
    // the JavaScript language.
    - (uint32_t)toUInt32;

    // If the value is a boolean, a NSNumber value of @YES or @NO will be returned.
    // For all other types the value will be copied to a number according to the
    // conversion specified by the JavaScript language.
    - (NSNumber *)toNumber;

    // The value is copied to a string according to the conversion specified by the
    // JavaScript language.
    - (NSString *)toString;

    // The value is converted to a number representing a time interval since 1970,
    // and a new NSDate instance is returned.
    - (NSDate *)toDate;

    // If the value is null or undefined then nil is returned.
    // If the value is not an object then a JavaScript TypeError will be thrown.
    // The property "length" is read from the object, converted to an unsigned
    // integer, and an NSArray of this size is allocated. Properties corresponding
    // to indicies within the array bounds will be copied to the array, with
    // Objective-C objects converted to equivalent JSValues as specified.
    - (NSArray *)toArray;

    // If the value is null or undefined then nil is returned.
    // If the value is not an object then a JavaScript TypeError will be thrown.
    // All enumerable properties of the object are copied to the dictionary, with
    // Objective-C objects converted to equivalent JSValues as specified.
    - (NSDictionary *)toDictionary;

Accessing Javascript Code in Objective-C

1).Evaluating Javascript Code

NSString * jsCode = @"1+2";
JSContext *context = [[JSContext alloc] init];
JSValue * value = [context evaluateScript:jsCode];
NSLog(@"Output = %d", [value toInt32]);

 

2).Access Javascript Variables. Variables and functions are accessed from JSContext.
To access varible from Javascript : context[@”x”]
To access function from javascript : context[@”myfun”]

JSContext *context = [[JSContext alloc] init];
	NSString * jsCode = @"var x; x=10;";
    [context evaluateScript:jsCode];

    JSValue * a =context[@"x"];
    NSLog(@"x = %d", [a toInt32]);

 

3).Access Javascript functions and execute them in Objective-C

//function with arguments
	JSContext *context = [[JSContext alloc] init];
	NSString * jsCode = @"function sum(a,b) { return a+b;} ";
    [context evaluateScript:jsCode];

    JSValue * func =context[@"sum"];
    NSArray * args = @[[NSNumber numberWithInt:10],[NSNumber numberWithInt:20]];
    JSValue * ret =[func callWithArguments:args];
    NSLog(@"10+20 = %d", [ret toInt32]);

    //function without arguments
    NSString * jsCode2 = @"function getRandom() { return parseInt(Math.floor((Math.random()*100)+1));} ";
    [context evaluateScript:jsCode2];

    JSValue * func2 =context[@"getRandom"];

    for(int i=0;i<5;i++)
    {
        JSValue * ret2 =[func2 callWithArguments:nil];
        NSLog(@"Random Value = %d", [ret2 toInt32]);
    }

Call Objective-C code from JavaScript

Objective-C code is called from JavaScript in two ways

1.Code Blocks

Objective-C code block can be called from JavaScript.

JSContext *context = [[JSContext alloc] init];

    //we are telling that "sum" is function, takes two arguments
    context[@"sum"] = ^(int arg1,int arg2)
    {
        return arg1+arg2;
    };

    NSString * jsCode =@"sum(4,5);";
    JSValue * sumVal = [context evaluateScript:jsCode];

    NSLog(@"Sum(4,5) = %d", [sumVal toInt32]);

    //we are telling that "getRandom" is function, does not take any arguments
    context[@"getRandom"] = ^()
    {
        return rand()%100;
    };

    NSString * jsCode2 =@"getRandom();";
    for(int i=0;i<5;i++)
    {
        JSValue * sumVal2 = [context evaluateScript:jsCode2];
        NSLog(@"Random Number = %d", [sumVal2 toInt32]);
    }

 

2.Using JSExport Protocol

You can see the comparison between Objective-C Object and it’s equivalent Javascript Object below.

@interface MyObject
@property  int x;

-(int) getX;
+(MyObject *) getSqure:(MyObject*)obj;

@end

//Usage:
MyObject * obj = [MyObject new];
[obj getX];
[MyObject getSqure:obj];
function MyObject()
{
	//member variable
	this.x=0;

	//instance method
	this.getX = function() 
                    { 
                    return this.x;
                    }
}

//static method
MyObject.getSqure = function(obj)
{
	var newObj = new MyObject();
	newObj.x = obj.x * obj.x;
	return newObj;
}

//Usage: 
var obj = new MyObject();
obj.x=10;
var sqrObj = MyObject.getSqure(obj);

To make Javascript interacting with Objective-C Object, We need to have a Protocol which should be inherited
from JSExport. Move all the variables and functions to prototype to access them in JavaScript.

@protocol MyObjectExport 
@property  int x;

-(int) getX;
+(MyObject *) getSqure:(MyObject*)obj;

@end

@interface MyObject :NSObject <MyObjectExport>

//this method is not accessible in javascript
-(void) test;

@end;

@implementation MyObject
@synthesize x;

-(int) getX
{
    return self.x;
}
+(MyObject *) getSqure:(MyObject*)obj;
{
    NSLog(@"Calling getSqure");
    MyObject * newObj = [MyObject new];
    newObj.x = obj.x * obj.x;

    return  newObj;
}

Now MyObject(Objective-C)’s variables and functions are directly accessed from javascript.

JSContext * context = [[JSContext alloc] init];
NSString * jsCode = @"function sqrtOf(obj){ return MyObject.getSqure(obj);}";

    //adding Objective-C Class to Javascript.
    context[@"MyObject"]=[MyObject class];

    [context evaluateScript:jsCode];

    MyObject * obj =[MyObject new];
    obj.x =10;

    JSValue * func =context[@"sqrtOf"];
    JSValue * val = [func callWithArguments:@[obj]];

    //we got MyObject from javascript.
    MyObject *sqrtObj = [val toObject];

    NSLog(@"Value =%d, %d", obj.x, [sqrtObj getX]);

About Author

I am a developer and I maintain the site https://hayageek.com. The best software developers are those who can think like both a developer and a user.
All posts by Ravishanker Kusuma