我需要在运行时中断[context evaluateScript:js]
,在文档和Google中找不到方法。谁能帮忙?
我无法通过JavaScriptCore
使它正常工作。我尝试过:
DispatchWorkItem
中并调用cancel()
Operation
中并尝试取消它,以及nil
对OperationQueue
进行编码(这实际上会导致应用程序崩溃)。JavaScriptCore
中的C API以及-fno-objc-arc
标志来手动管理内存。没有这些工作。
什么完成工作使用WKWebView
,并且一旦使用nil
,evaluateJavaScript
函数就会调用其完成处理程序。我发布了一个示例here。
对于任何尝试这样做的人,请记住,这是未记录的行为,因此在以后的任何iOS版本中都可能会更改。
如果使用JSContext
的evaluateJavaScript
方法。由于上下文中没有取消方法,因此您无法停止它。 iOS不喜欢macOS可以使用XPC,因此无法停止外部运行环境。
但是,有一种解决方法。只是认为JSContext
喜欢浏览器。脚本在进行中。如何通过外部事件停止它。最方便的方法是构造自己的运行循环。将任务缩小并放在队列中。
我导出一个本机计时器,每隔几秒钟就会在一次downloadWithHandler methold上调用javascript处理程序,并将isCancelled
设置为true。运行循环将停止,并且JSContext eval到达整个脚本的结尾并返回。
本机:
let script = viewModel.string
let context = EAJSContext()!
// context will be dealloc after finish if not retain here.
// not retain it to debugging
// viewModel.context = context
DispatchQueue.global(qos: .background).async {
// inject helper metholds
JavaScriptCoreHelper().config(context: context)
// export download(handler:) method
Emulator.configure(context: context)
let result = context.evaluateScript(script)
print("context return result: \(result)")
}
脚本:
var emulator = Emulator.create();
var taskIsFinish = false;
const promiseA = new Promise( (resolve, reject) => {
emulator.downloadWithHandler( (response) => {
// native pass dictionary
var isFinish = response["isFinish"];
var isCancelled = response["isCancelled"];
var date = response["date"];
console.log("isFinish: " + isFinish);
console.log("isCancelled: " + isCancelled);
console.log("date: " + date);
if (isFinish || isCancelled) {
resolve(date);
}
});
});
promiseA
.then( (val) => {
console.log("asynchronous logging has val: " + val)
taskIsFinish = true
})
while(!taskIsFinish) {
// long task in queue
sleep(1);
console.log('long task');
}
输出:
2020-05-10 04:07:06.766592+0800 …[34354:2831281] [interaction] … runToolbarItemPressed(_:): run triggerd
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:06 GMT+0800 (CST)
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:06 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:07 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:08 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:10 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: false
console.log: date: Sun May 10 2020 04:07:11 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: true
console.log: date: Sun May 10 2020 04:07:12 GMT+0800 (CST)
console.log: asynchronous logging has val: Sun May 10 2020 04:07:12 GMT+0800 (CST)
console.log: long task
console.log: isFinish: false
console.log: isCancelled: true
console.log: date: Sun May 10 2020 04:07:13 GMT+0800 (CST)
context return result: Optional(undefined)
console.log: isFinish: false
console.log: isCancelled: true
console.log: date: Sun May 10 2020 04:07:13 GMT+0800 (CST)
console.log: isFinish: false
console.log: isCancelled: true
console.log: date: Sun May 10 2020 04:07:13 GMT+0800 (CST)
2020-05-10 04:07:13.391950+0800 …[34354:2831310] [debug] EAJSContext.swift[16], deinit
((如果评估完成后上下文未取消初始化,则内存可能正在泄漏。)>
包装本机Worker类中的上下文。并设置标志,以使该任务在任务取消时快速返回带有空结果的回调。不要保留并丢弃它。