JavaScriptCore – 将函数作为parameter passing给ObjC

我有一个利用JavaScriptCore的UIWebView。 我试图从网页调用一个ObjC函数。 但是,该函数需要asynchronous调用,所以我传递了一个callback函数,当调用asynchronousObjC函数时调用。

这是我的理解,JS函数通过桥梁相当于NSBlock。 我现在的代码是:

context[@"currentUserLocation"] = ^( void(^callback)(NSString* str) ) { NSLog(@"Starting Async Function"); //generic async function dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"delay complete"); callback( @"return value" ); }); }; 

我在做什么有什么根本性的错误? 从表面上看,ObjC似乎不知道在哪个上下文中运行callback函数。

我花了一点时间才得以解决这个问题。 诀窍是不要将callback参数看作是一个块,而是一个JSValue,然后使用JSValue API调用它:

 context[@"currentUserLocation"] = ^(JSValue *callback) { NSLog(@"Starting Async Function"); //generic async function dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"delay complete"); //Check we actually have a callback (isObject is the best we can do, there is no isFunction) if ([callback isObject] != NO) { //Use window.setTimeout to schedule the callback to be run [context[@"setTimeout"] callWithArguments:@[callback, @0, @"return value"]]; } }); }; 

在window.setTimeout()调用中包装callback允许JSVirtualMachine负责调度和线程,如果任何UI工作由callback完成,我发现直接调用callback通常会导致死锁。