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.
To access JavaScript framework, you need to include the header file
|
1
|
#import <JavaScriptCore/JavaScriptCore.h> |
List of Main Classes supported by framework:
JSContext : For any javascript operations you need JSContext.
|
1
|
JSContext *context = [[JSContext alloc] init];
|
JSValue : JSValue holds JavaScript values,variables and functions. List of main methods in JSValue.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// 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
|
1
2
3
4
|
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"]
|
1
2
3
4
5
6
|
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
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//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.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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.
|
|
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.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@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.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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]);
|