JavaScriptCore-将函数作为参数传递给ObjC [英] JavaScriptCore -- Passing a function as a parameter to ObjC

查看:145
本文介绍了JavaScriptCore-将函数作为参数传递给ObjC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个利用JavaScriptCore的UIWebView.我正在尝试从网页调用ObjC函数.但是,该函数需要异步调用,因此我传递了一个在调用异步ObjC函数时调用的回调函数.

I have a UIWebView that utilizes JavaScriptCore. I'm trying to call an ObjC function from an web page. However, the function needs to be call asynchronously, so I'm passing in a callback function that is called when the async ObjC function is called.

据我了解,JS函数通过桥等效于NSBlock.我当前拥有的代码是:

It is my understanding that JS functions are equivalent to NSBlock via the bridge. The current code I have is:

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似乎不知道在哪个上下文中运行回调函数.

Is there something fundamentally wrong with what I'm doing? On the surface it seems like ObjC won't know what context to run the callback function in.

推荐答案

花了我一些时间才能解决这个问题.诀窍不是将回调参数视为一个块,而是一个JSValue,然后使用JSValue API对其进行调用:

It took me a little while to get the hang of this. The trick is not to think of the callback argument as a block, but a JSValue and then call it using the 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()调用中允许JSVirtualMachine进行调度和线程处理,我发现如果通过回调完成任何UI工作,直接调用回调通常会导致死锁.

Wrapping the callback in a window.setTimeout() call allows the JSVirtualMachine to take care of scheduling and threading, I have found calling the callback directly often leads to deadlocks if any UI work is done by the callback.

这篇关于JavaScriptCore-将函数作为参数传递给ObjC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆