erm*_*410 7 objective-c ios javascriptcore
使用JSContextfrom a a UIWebView创建了一个作为Objective C块实现的javascript函数:
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];
}
Run Code Online (Sandbox Code Playgroud)
此函数将回调作为参数,并NSOperationQueue在调用回调之前执行一些工作,如:
- (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]];
});
}
}
Run Code Online (Sandbox Code Playgroud)
除非回调包含对alert()以下内容的调用,否则这样可以正常工作
//This javascript is part of the page in the UIWebView
window.aFunc("important information", function(arg) { alert("Got " + arg); });
Run Code Online (Sandbox Code Playgroud)
在这种情况下,警报显示并且UI变得完全没有响应.我假设关闭警报的触摸事件被该警报阻止的事件.
如果我在没有调度的情况下调用回调(换句话说就是在哪个线程MyOperation上运行),它运行得很好,但我的印象是任何可能具有UI含义的代码(换句话说,任何JS回调)应始终在主线程上运行.我错过了什么,或者alert()在使用JavaScriptCore框架时是否真的无法安全使用?
经过几天看着线程的堆栈跟踪等待对方,解决方案非常简单我不会感到惊讶我忽略了它,而不是尝试更复杂的东西.
如果你想UIWebView异步回调一个javascript,请使用window.setTimeout并让JSVirtualMachine负责排队回调.
只需更换
dispatch_async(dispatch_get_main_queue(), ^{
[self.callback callWithArguments:@[arg]];
});
Run Code Online (Sandbox Code Playgroud)
同
dispatch_async(dispatch_get_main_queue(), ^{
[self.callback.context[@"setTimeout"] callWithArguments:@[self.callback, @0, arg]];
});
Run Code Online (Sandbox Code Playgroud)