Cocoa プログラミング
JavaScriptCore
JavaScriptCore では、Objective-C や Swift で記載した独自のクラスも利用できるようになっています。
このクラスの中で JavaScript に固有な undefined の値を扱う方法を調べてみました。
JavaScriptCore で undefined を扱えるメソッドを実装する
JavaScriptCore.framework を使った JavaScript の実行環境では、Objective-C や Swift で記載した独自のクラスも利用できるようになっています。
JSExport
プロトコルを継承したプロトコルで定義した機能であれば JavaScript から自由に実行できます。引数や戻り値も、プリミティブ型やNSString
などの基本的なオブジェクトの他にも、JSExport
に対応したオブジェクトであれば、普段通りの実装で自由にやり取りできるようになっています。
JavaScriptCore でundefined
を引数や戻り値に使うには
さて、Objective-C や Swift になくて JavaScript に存在するのがundefined
という値です。
要は未定義値 というもので、空を示すnull とも違う、そもそも存在していないものという意味の値になります。
この値を JavaScriptCore で使えるクラスで扱いたい場合には、その値をJSValue
型で扱うようにします。
このJSValue
型というのは、JavaScriptCore 内で扱う JavaScript の変数の型です。
JavaScript の変数では型を気にせず自由に扱えるバリアント型
になっていますが、このJSValue
型が、さまざまな型を一手に引き受けるバリアント型の機能を担っています。
JavaScriptCore のevaluateScript:
メソッドを使うと、実行した JavaScript の戻り値がこの型で取得できるので、JavaScriptCore を使い始めてしばらくした人にはきっとお馴染みのオブジェクトでしょう。
このオブジェクトを独自のクラスの引数や戻り値として使うことで、undefined
を含むバリアント型の自由な値を、独自のクラスで利用できるようになります。
戻り値でundefined
を返すメソッド
たとえば、NSDictionary
型の変数options
から、キーを指定して値を取得するメソッドを JavaScript から呼び出せるようにするとします。
このとき変数options
に存在するキーが指定された場合はその値を文字列型で返し、指定されたキーが存在しなかった場合は JavaScript 固有のundefined
を返すようにしたい場合は、次のようにしてそれを実現できます。
- (JSValue*)getOption:(NSString*)key
{
if ([options.allKeys containsObject:key])
{
return [JSValue valueWithObject:options[key] inContext:[JSContext currentContext]];
}
else
{
return [JSValue valueWithUndefinedInContext:[JSContext currentContext]];
}
}
このように、オブジェクトを指定してJSValue
を作るときにはvalueWithObject:inContext:
メソッドを、undefined
なJSValue
を作るときにはvalueWithUndefinedInContext:
メソッドを使用します。他にもBOOL
などのプリミティブ型用のメソッドも用意されています。
これらのメソッドには、その値を使用するJSContext
を渡す必要がありますが、現在有効なコンテキストは[JSValue currentContext]
で取得できます。
引数でundefined
を受け取るメソッド
引数でundefined
を受け取りたい場合も同様にJSValue
を使用します。
たとえば文字列を受け取りたい引数の型をJSValue
にすると、JavaScript から文字列やundefined
が渡されたときに、それを一緒くたにして受け取れます。
あとはJSValue
のisUndefined
メソッドを使って引数の値がundefined
だったときに特別な処理を実行したり、undefined
でなければtoString
メソッドを使ってNSString
型の値として取り出したりできます。