JavaScriptからObjective-Cに渡したArrayでの注意その2

11/7追記:WebKit DOM Programming TopicsのCalling Objective-C Methods From JavaScriptに書いてあった。WebKit側の資料しか見てなかったから気づかなかったorz

Other JavaScript objects are wrapped as WebScriptObject instances.

As an exception, JavaScript arrays cannot be cleanly mapped to NSArray objects because they are a hybrid between a numerically-indexed array and an associative array. To avoid loss of data during the mapping, you must instead use the webScriptValueAtIndex: and setWebScriptValueAtIndex:value: methods.

webScriptValueAtIndex:とsetWebScriptValueAtIndex:value:ね。


NSArrayとしてそのまま扱うのは駄目な感じでした。
Objective-Cの世界でNSArrayとして普通に使うには、JS側から配列のサイズも一緒に渡すなり、文字列とかの配列ならjoinで結合しちゃって文字列として渡して、Objective-C側でNSArrayを作るなどする必要がある。


JSとObjective-Cでのやり取りに必要な下準備は省略するので、そこの部分であれっとなった場合はこちらを。
http://d.hatena.ne.jp/yuichi_katahira/20121007/1349577340


単純にJavaScriptObjective-CとArrayを渡してみる。

function testMethod() {
  window.objC.callFromJSObjCMethod_(["a","b","c"]);
}
- (void)callFromJSObjCMethod:(NSArray *)fromJSArray
{
  //WebScriptObject count呼んで unrecognized selector sent to instance xxxxx とエラーでます。
  NSLog(@"%ld",[fromJSArray count]);
  //count使えないので、forループができません。なので、for-inとかも当然エラー
  //↓NG
 for (NSString *s in fromeJSArray) {
    NSLog(@"%@",s);
  }
}


配列のサイズも渡す版

function testMethod() {
  var array = ["a","b","c"];
  window.objC.callFromJSObjCMethod_withCount_(array,array.length);
}
- (void)callFromJSObjCMethod:(NSArray *)fromJSArray withCount:(NSNumber *)jsArrayCount
{
  NSMutableArray *workArray = [NSMutableArray array];  
  int targetLength = [jsArrayCount intValue];
  int i;
  for (i = 0; i<targetLength; i++) {
    [workArray addObject:[fromJSArray objectAtIndex:i]];
  }
  //workArrayを使ってなにか処理
}


Array.join()を使って文字列として渡してしまう版

function testMethod() {
  window.objC.callFromJSObjCMethod_(["a","b","c"].join());
}
- (void)callFromJSObjCMethod:(NSString *)fromJSArrayStrings
{
  NSArray *workArray = [fromJSArrayStrings componentsSeparatedByString:@","];
  //workArrayを使ってなにか処理
}

以上。