7

WebViewインスタンス内のJavaScriptとの間で通信する場合WebViewDelegate、JavaScriptタイプとObjective-Cタイプは相互に変換されます。たとえば、JavaScriptからObjective-C関数を呼び出すと、文字列は。になりNSString、数値は。NSNumberになり、オブジェクトは。になりWebScriptObjectます。

他のものは扱いが非常に簡単ですが、WebScriptObject奇妙に思えます。

のような辞書を渡すとき、私が見るコードのほとんどは、次のよう{"foo": 1, "bar": 2}に、を使用してプロパティを抽出します。valueForKey[[arg valueForKey:@"foo"] intValue] == 1

しかし、プロパティが存在するかどうかわからない場合はどうでしょうか。キーがオプションの場合はどうなりますか?[arg valueForKey:@"baz"]例外をスローします。

私にできることの1つは

@try {
  foo = [[arg valueForKey:@"baz"] intValue];
}
@catch (NSException* e) {
  foo = 0;
}

しかし、Objective-Cの例外は安全ではなく、フロー制御に使用すべきではないと聞いています。

私が考えることができる他の唯一の方法は、ここで使用される方法のいくつかのバリエーションです:http: //edotprintstacktrace.blogspot.com/2011/10/sample-webscriptobject-javascript.html

言い換えると、1。を使用evaluateWebScriptして実装するJavaScript関数を定義しますObject.keys。2。その関数を呼び出しますWebScriptObject。3。返されたキーの配列を反復処理しvalueForKey、一致するものが見つかった場合にのみ呼び出します。

これは私には信じられないほど非効率に思えます。もっと良い方法があるに違いない...ありますか?

4

2 に答える 2

4

OS X 10.9 および iOS 7 以降、これを行うためのより簡単な方法があります。JSValueApple は、 JavaScript オブジェクトを通常の ObjC オブジェクトにブリッジするために使用できるという名前のクラスを導入しました。

// WebScriptObject *options; obtained from a callback in ObjC
id objCObject = [[options JSValue] toObject];

if ([objCObject isKindOfClass:[NSArray class]]) {
    for (id object in objCObject) {
        NSLog(@"object: %@", object);
    }
}
else if ([objCObject isKindOfClass:[NSDictionary class]]) {
    for (id<NSCopying> key in [objCObj allKeys]) {
       NSLog(@"object for key %@: %@", key, [objCObject objectForKey:key]);
    }
}
于 2015-01-14T14:37:43.050 に答える
3

機能するものを見つけたと思います-トリックは、-JSObjectを使用してWebScriptObjectをJSObjectRefに変換できることです。JSObjectRefで機能するCメソッドがたくさんありますが、ドキュメントが少し不足しているため、何をすべきかを理解するのは困難です正確に行います。

プロパティが存在するかどうかを確認する方法は次のとおりです。

id getProperty(WebScriptObject *obj, NSString *prop) {
    JSStringRef jsProp = JSStringCreateWithCFString((__bridge CFStringRef) prop);

    if (JSObjectHasProperty(self.frame.globalContext, [obj JSObject], jsProp)) {
       return [options valueForKey:prop];
    } else {
       return nil;
    }

    JSStringRelease(jsString);
}

すべてのプロパティ (キーが事前にわかっていない) を一覧表示する場合は、さらにいくつかの関数を使用する必要があります。

JSPropertyNameArrayRef properties =
    JSObjectCopyPropertyNames(self.frame.context, [obj JSObject]);

size_t count = JSPropertyNameArrayGetCount(properties);

for (NSInteger i = 0; i < count; i++) {
    JSStringRef property = JSPropertyNameArrayGetNameAtIndex(properties, i);
    // ... etc. as above
}
于 2013-12-04T23:56:33.803 に答える