如何停止JSContext在iOS中评估JavaScript?

时间:2018-06-26 01:39:01

标签: ios objective-c javascriptcore

运行时需要顶部中断[context evaluateScript:js],但是在文档和Google中找不到方法。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

如果您使用JSContext的{​​{1}}方法。由于上下文中没有取消方法,因此您无法停止它。而且iOS不喜欢macOS可以使用XPC,因此无法停止外部运行环境。

但是,有一种解决方法。只是认为evaluateJavaScript喜欢浏览器。脚本在进行中。如何通过外部事件停止它。最方便的方法是构造自己的运行循环。将任务缩小并放入队列。

自定义运行循环

我导出了一个本地计时器,每隔几秒钟就会在一次downloadWithHandler methold上调用javascript处理程序,并将JSContext设置为true。运行循环将停止,并且JSContext eval到达整个脚本的结尾并返回。

母语:

isCancelled

脚本:

    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');
}

(如果评估完成后上下文未取消初始化,则内存可能正在泄漏。)

其他想法

包装本机Worker类中的上下文。并设置标志,以使该任务在任务取消时快速返回带有空结果的回调。不要保留并扔掉它。

答案 1 :(得分:0)

我无法使用JavaScriptCore使它正常工作。我尝试过:

  • 将代码包装在DispatchWorkItem中,然后调用cancel()
  • 将代码包装在Operation中,然后尝试将其取消,以及nilOperationQueue进行编码(实际上会导致应用崩溃)。
  • 使用JavaScriptCore中的C API和-fno-objc-arc标志来手动管理内存。

这些都不起作用。

已完成的工作是使用WKWebView,一旦nil被使用,evaluateJavaScript函数就会调用其完成处理程序。我发布了一个示例here

对于任何尝试这样做的人,请记住这是未记录的行为,因此在以后的任何iOS版本中都可能会更改。