JavaScriptCore.framework とは
Mac/iOS アプリケーション内に JavaScript 実行環境を組み込める。
Objective-C クラスをエクスポートしたり、JavaScript で処理させて結果を取り出したりできる。
要は Lua みたいに JavaScript を組み込み言語として使えちゃう!
準備
- MacOS SDK 10.9 または iOS SDK 7.0 以降が必要。
- Xcode プロジェクトに JavaScriptCore.framework を追加する。
使い方
クラスの定義とエクスポートの指定
Vector2 というクラスを JavaScript から利用できるようにするには、JSExport プロトコルに準拠したプロトコルを定義し、ここにエクスポートするメソッドやプロパティを記述する。
@class Vector2;
@protocol Vector2JSExport <JSExport>
+ (id)new;
+ (Vector2*)vector2WithX:(float)x andY:(float)y;
+ (Vector2*)vector2WithArray:(NSArray*)array;
+ (Vector2*)vector2WithObject:(NSDictionary*)dict;
- (NSString*)description;
@property (nonatomic, assign) float x;
@property (nonatomic, assign) float y;
@end
@interface Vector2 : NSObject <Vector2JSExport>
+ (Vector2*)vector2WithX:(float)x andY:(float)y;
+ (Vector2*)vector2WithArray:(NSArray*)array;
+ (Vector2*)vector2WithObject:(NSDictionary*)dict;
@property (nonatomic, assign) float x;
@property (nonatomic, assign) float y;
@end
JavaScript 実行環境を作る
JS 仮想マシンとコンテキストを作成。
例外ハンドラも設定しておくとよい。
JSVirtualMachine* vm = [[JSVirtualMachine alloc] init];
JSContext* ctx = [[JSContext alloc] initWithVirtualMachine:vm];
// 例外ハンドラを設定
ctx.exceptionHandler = ^(JSContext* ctx, JSValue* error) {
NSLog(@"JS Exc: %@", error);
};
コンテキストにエクスポートしたいクラス定義を投入。
ブロックや値を投入することも可能。
// Vector2 クラスを投入
ctx[@"Vector2"] = [Vector2 class];
// log 関数を追加
ctx[@"log"] = ^(JSValue* value) { NSLog(@"%@", value); };
試してみる
// log() を呼んでみる
[ctx evaluateScript:@"log('xxxxx');"];
// Vector2 をインスタンス化してみる
[ctx evaluateScript:@"var v1 = Vector2.new();"];
// プロパティに代入してみる
[ctx evaluateScript:@"v1.x = 1.0; v1.y = 2.0;"];
// description() の戻り値を取得してみる
NSLog(@"%@", [ctx evaluateScript:@"v1.description();"]);
// 2 つ以上の引数があるメソッドの呼び出し方はこんな感じ
[ctx evaluateScript:@"Vector2.vector2WithXAndY(30, 40);"];
// 配列の扱い
[ctx evaluateScript:@"Vector2.vector2WithArray([500, 600]);"];
// 辞書の扱い
[ctx evaluateScript:@"Vector2.vector2WithObject({x: 7000, y: 8000});"];
// コンテキストから値を取得してみる
NSLog(@"v1 = %@", ctx[@"v1"]);