调用alert()时,调用[JSValue callWithArguments:]会锁定UI [英] Calling [JSValue callWithArguments:] locks UI when alert() is called
问题描述
从 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屋!