调用alert()时,调用[JSValue callWithArguments:]会锁定UI [英] Calling [JSValue callWithArguments:] locks UI when alert() is called

查看:602
本文介绍了调用alert()时,调用[JSValue callWithArguments:]会锁定UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UIWebView 中使用 JSContext 我创建了一个以Objective C块实现的javascript函数:

Using the JSContext from a UIWebView I have created a javascript function that is implemented as an Objective C block:

JSContext *js = ... //get contect from web view
js[@"aFunc"] = ^(JSValue *aString, JSValue *callback) {
    NSString *realString = [aString toString];
    MyOperation *op = [[MyOperation alloc] initWithString:realString andCallback:callback];

    //Do some heavy lifting in background
    [self.myQueue addOperation:op];
}

此函数将回调作为参数并在<$中执行一些工作c $ c> NSOperationQueue 在调用回调之前,如:

This function takes a callback as an argument and performs some work in an NSOperationQueue before calling the callback like:

- (void)main {
    JSValue *arg = [self theHeavyWork];
    //Now we have finished the heavy work, switch back to main thread to run callback (if any).
    if ([self.callback isObject] != NO) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.callback callWithArguments:@[arg]];
        });
    }
}

这个工作正常,除非回调包含对 alert()

This works fine, unless the callback contains a call to alert():

//This javascript is part of the page in the UIWebView
window.aFunc("important information", function(arg) { alert("Got " + arg); });

在这种情况下,警报显示并且UI变得完全没有响应。我假设关闭警报的触摸事件正被阻止的警报阻止。

In this case the alert shows and the UI becomes completely unresponsive. I am assuming that the event the touch event to close the alert is being blocked by the alert being there.

如果我在没有调度的情况下调用回调(换句话说就是哪个线程 MyOperation 正在运行)它工作正常,但我的印象是任何可能具有UI含义的代码(换句话说,任何JS回调)都应该总是在主线程上运行。我是否遗漏了某些内容,或者在使用 alertCore 框架时,是否真的无法安全地使用 alert()? / p>

If I call the callback without the dispatch (in other words on which ever thread the MyOperation is running on) it works just fine, but I was under the impression that any code that could have UI implications (in other words any JS callbacks) should always be run on the main thread. Am I missing something, or do is it really impossible to safely use alert() when using the JavaScriptCore framework?

推荐答案

几天后看着线程的堆栈跟踪等待对方,解决方案非常简单我并不感到惊讶忽略它有利于尝试更复杂的东西。

After a couple days looking at stack traces of threads waiting for each other, the solution was so simple I'm not surprised I overlooked it in favor of trying more complicated stuff.

如果你想回调到 UIWebView 的javascript异步,使用 window.setTimeout 并让 JSVirtualMachine 负责排队回调。

If you want to call back into a UIWebView's javascript asynchronously, use window.setTimeout and let the JSVirtualMachine take care of queuing the callback.

只需替换

dispatch_async(dispatch_get_main_queue(), ^{
    [self.callback callWithArguments:@[arg]];
});

with

dispatch_async(dispatch_get_main_queue(), ^{
    [self.callback.context[@"setTimeout"] callWithArguments:@[self.callback, @0, arg]];
});

这篇关于调用alert()时,调用[JSValue callWithArguments:]会锁定UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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