Arj*_*hta 3 javascript objective-c javascriptcore ios7
我一直在尝试新的Objective C JavascriptCore框架.
这很疯狂,但它似乎没有setTimeout或setInterval.哪个......我不明白.
我可以在Objective C中创建计时器,但我的大部分库都是用Javascript编写的,除此之外,看起来很奇怪没有setInterval或者setTimeout!!
我尝试了一些替代方法:
window.setInterval(function(){ /* dosomething */ }, 1000);
setInterval(function(){ /* dosomething */ }, 1000);
var interval;
interval = window.setInterval(function(){ /* dosomething */ }, 1000);
interval = setInterval(function(){ /* dosomething */ }, 1000);
Run Code Online (Sandbox Code Playgroud)
我无法监视JSVirtualMachine中甚至发生的事情.我所知道的是我的代码在setInterval被叫时停止工作.
任何帮助超级赞赏!
解决旧问题的新实现.
setTimout,setInterval并且clearTimeout在JavaScriptCore的上下文中不可用.
你需要自己实现它.我已经创建了一个快速的3类来解决这个问题.通常,示例仅显示setTimeout没有使用选项的功能clearTimeout.如果您正在使用JS依赖项,那么您很可能也需要这些clearTimeout和setInterval函数.
import Foundation
import JavaScriptCore
let timerJSSharedInstance = TimerJS()
@objc protocol TimerJSExport : JSExport {
func setTimeout(_ callback : JSValue,_ ms : Double) -> String
func clearTimeout(_ identifier: String)
func setInterval(_ callback : JSValue,_ ms : Double) -> String
}
// Custom class must inherit from `NSObject`
@objc class TimerJS: NSObject, TimerJSExport {
var timers = [String: Timer]()
static func registerInto(jsContext: JSContext, forKeyedSubscript: String = "timerJS") {
jsContext.setObject(timerJSSharedInstance,
forKeyedSubscript: forKeyedSubscript as (NSCopying & NSObjectProtocol))
jsContext.evaluateScript(
"function setTimeout(callback, ms) {" +
" return timerJS.setTimeout(callback, ms)" +
"}" +
"function clearTimeout(indentifier) {" +
" timerJS.clearTimeout(indentifier)" +
"}" +
"function setInterval(callback, ms) {" +
" return timerJS.setInterval(callback, ms)" +
"}"
)
}
func clearTimeout(_ identifier: String) {
let timer = timers.removeValue(forKey: identifier)
timer?.invalidate()
}
func setInterval(_ callback: JSValue,_ ms: Double) -> String {
return createTimer(callback: callback, ms: ms, repeats: true)
}
func setTimeout(_ callback: JSValue, _ ms: Double) -> String {
return createTimer(callback: callback, ms: ms , repeats: false)
}
func createTimer(callback: JSValue, ms: Double, repeats : Bool) -> String {
let timeInterval = ms/1000.0
let uuid = NSUUID().uuidString
// make sure that we are queueing it all in the same executable queue...
// JS calls are getting lost if the queue is not specified... that's what we believe... ;)
DispatchQueue.main.async(execute: {
let timer = Timer.scheduledTimer(timeInterval: timeInterval,
target: self,
selector: #selector(self.callJsCallback),
userInfo: callback,
repeats: repeats)
self.timers[uuid] = timer
})
return uuid
}
func callJsCallback(_ timer: Timer) {
let callback = (timer.userInfo as! JSValue)
callback.call(withArguments: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
jsContext = JSContext()
TimerJS.registerInto(jsContext: jsContext)
Run Code Online (Sandbox Code Playgroud)
我希望有所帮助.:)
我知道我在回答一个老问题,但是当我将JavaScriptCore移植到 Android 时,我遇到了这个问题。
setTimeout并且setInterval不是纯 JavaScript 的一部分。它们是 DOM 的一部分。就像document并且xmlHttpRequest在 JavaScriptCore 中不可用一样。JavaScript 被设计为单线程、同步执行环境。来自主机的调用,代码被执行,然后返回。这就是它所做的一切。主机支持发生的任何其他魔法。
所以为了在你的代码中支持它,你必须在主机端实现它。这很容易完成,如下所示:
context[@"setTimeout"] = ^(int ms, JSValue *callback) {
[NSTimer scheduledTimerWithTimeInterval:ms/1000
target:[NSBlockOperation blockOperationWithBlock:^{
[callback callWithArguments:nil];
}]
selector:@selector(main)
userInfo:nil
repeats:NO
];
}
Run Code Online (Sandbox Code Playgroud)
不过,你需要小心。如前所述,JS 没有信号量保护或任何类似的东西。要正确实现这一点,您应该创建一个单独的执行线程:
dispatch_queue_t jsQueue = dispatch_queue_create("com.some.identifier",
DISPATCH_QUEUE_SERIAL);
Run Code Online (Sandbox Code Playgroud)
然后在执行代码时,始终在此队列中运行它:
dispatch_async(jsQueue, ^{
[context executeScript:myJSCode];
});
Run Code Online (Sandbox Code Playgroud)
最后,您可以将上述setTimeout函数改写如下:
context[@"setTimeout"] = ^(int ms, JSValue *callback) {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:ms/1000
target:[NSBlockOperation blockOperationWithBlock:^{
dispatch_async(jsQueue, ^{
[callback callWithArguments:nil];
});
}]
selector:@selector(main)
userInfo:nil
repeats:NO
];
};
Run Code Online (Sandbox Code Playgroud)
现在它是线程安全的并且会做你期望的事情。