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.
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. - (int 3 2 _t)toInt 3 2 ; // The value is copied to an integer according to the conversion specified by // the JavaScript language. - (uint 3 2 _t)toUInt 3 2 ; // 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 : 1 0 ],[ NSNumber numberWithInt : 2 0 ]]; JSValue * ret =[func callWithArguments :args]; NSLog( @"10+20 = %d" , [ret toInt32 ]); //function without arguments NSString * jsCode 2 = @"function getRandom() { return parseInt(Math.floor((Math.random()*100)+1));} " ; [context evaluateScript :jsCode 2 ]; JSValue * func 2 =context[ @"getRandom" ]; for ( int i= 0 ;i< 5 ;i++) { JSValue * ret 2 =[func 2 callWithArguments :nil ]; NSLog( @"Random Value = %d" , [ret 2 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 arg 1 , int arg 2 ) { return arg 1 +arg 2 ; }; 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()% 1 0 0 ; }; NSString * jsCode 2 = @"getRandom();" ; for ( int i= 0 ;i< 5 ;i++) { JSValue * sumVal 2 = [context evaluateScript :jsCode 2 ]; NSLog( @"Random Number = %d" , [sumVal 2 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 = 1 0 ; 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 ]); |