如何将 JS 函数作为对象 属性 传递给 iOS
How to pass a JS function as object property to iOS
我有一个名为 ChannelExport
的 JSExport
协议,方法为 - (void)sendRequest:(NSDictionary *)request withCallback:(JSValue *)callback;
。从 Javascript 代码调用此方法工作正常,如下所示:
channel.sendRequestWithCallback({'foo': 'bar'}, function(response) { ... });
在 ObjC 中,我可以访问 request
字典中的值,还可以调用 callback
函数。
现在我想将接口更改为 - (void)sendRequest:(NSDictionary *)request
,将 JS 函数作为 request
字典的一部分传递,如下所示:
channel.sendRequestWithCallback({
'foo': 'bar'
'callback': function(response) { ... }
});
在这种情况下,当我尝试调用 ObjC 中的 callback
函数时,应用程序崩溃了。显然 callback
对象不是 JSValue
,而是 NSDictionary
(更准确地说,是 __NSDictionaryM
)。我假设 JS 函数被正确包装为 JSValue
,就像将它作为简单参数传递时一样。
任何提示为什么会发生这种情况,以及如何解决这个问题?
您不能使用 - (void)sendRequest:(NSDictionary *)request
签名来实现您的目标。如果将参数定义为 NSDictionary
,JavaScriptCore 将递归地将此字典中的所有对象转换为相应的 Objective-C 对象。使用 - (void)sendRequest:(JSValue *)requestValue
代替:
- (void)sendRequest:(JSValue *)requestValue {
JSValue *fooJSValue = [requestValue valueForProperty:@"foo"];
NSString *bar = [fooJSValue isUndefined] ? nil : fooValue.toString;
// use bar
JSValue *callback = [requestValue valueForProperty:@"callback"];
[callback callWithArguments:myArguments];
}
我有一个名为 ChannelExport
的 JSExport
协议,方法为 - (void)sendRequest:(NSDictionary *)request withCallback:(JSValue *)callback;
。从 Javascript 代码调用此方法工作正常,如下所示:
channel.sendRequestWithCallback({'foo': 'bar'}, function(response) { ... });
在 ObjC 中,我可以访问 request
字典中的值,还可以调用 callback
函数。
现在我想将接口更改为 - (void)sendRequest:(NSDictionary *)request
,将 JS 函数作为 request
字典的一部分传递,如下所示:
channel.sendRequestWithCallback({
'foo': 'bar'
'callback': function(response) { ... }
});
在这种情况下,当我尝试调用 ObjC 中的 callback
函数时,应用程序崩溃了。显然 callback
对象不是 JSValue
,而是 NSDictionary
(更准确地说,是 __NSDictionaryM
)。我假设 JS 函数被正确包装为 JSValue
,就像将它作为简单参数传递时一样。
任何提示为什么会发生这种情况,以及如何解决这个问题?
您不能使用 - (void)sendRequest:(NSDictionary *)request
签名来实现您的目标。如果将参数定义为 NSDictionary
,JavaScriptCore 将递归地将此字典中的所有对象转换为相应的 Objective-C 对象。使用 - (void)sendRequest:(JSValue *)requestValue
代替:
- (void)sendRequest:(JSValue *)requestValue {
JSValue *fooJSValue = [requestValue valueForProperty:@"foo"];
NSString *bar = [fooJSValue isUndefined] ? nil : fooValue.toString;
// use bar
JSValue *callback = [requestValue valueForProperty:@"callback"];
[callback callWithArguments:myArguments];
}