如何安全地读取WebScriptObject的属性?

Zar*_*rel 7 javascript webkit objective-c webview

WebView实例中的WebViewDelegateJavaScript 与a 之间进行通信时,JavaScript类型和Objective-C类型会来回转换.例如,当从JavaScript调用Objective-C函数时,字符串变为a NSString,数字变为a NSNumber,而Object变为a WebScriptObject.

其他的很简单,但WebScriptObject似乎很奇怪.

当传递类似的字典时{"foo": 1, "bar": 2},我看到的大多数代码都使用提取属性valueForKey,例如in[[arg valueForKey:@"foo"] intValue] == 1

但是如果你不确定该物业是否存在呢?如果键是可选的怎么办?[arg valueForKey:@"baz"]抛出一个例外.

我能做的一件事就是

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

但是我听说Objective-C中的例外是不安全的,不应该用于流量控制.

我能想到的另一种方法是这里使用的方法的一些变化:http://edotprintstacktrace.blogspot.com/2011/10/sample-webscriptobject-javascript.html

换句话说:1.用于evaluateWebScript定义实现的JavaScript函数Object.keys2.在您的WebScriptObject3. 上调用该函数迭代返回的键数组,并且只有valueForKey在找到匹配项时才调用.

对我来说,这看起来非常低效.必须有更好的方式......有吗?

Kub*_*der 3

我想我找到了一些有用的东西 - 诀窍是你可以使用 -JSObject 将 WebScriptObject 转换为 JSObjectRef,并且有一大堆可用于 JSObjectRefs 的 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);
}
Run Code Online (Sandbox Code Playgroud)

如果您想列出所有属性(其键事先不知道),您将需要使用更多函数:

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
}
Run Code Online (Sandbox Code Playgroud)