在UIWebView中挂起Javascript执行

Suspend Javascript execution in UIWebView

本文关键字:Javascript 执行 挂起 UIWebView      更新时间:2023-09-26

我成功地使用了一个不可见的UIWebView作为Javascript片段的执行引擎。与某些页面所建议的相反,它不需要是可见的。如果只是作为宣布死亡

UIWebView* myJSExecutor = [UIWebView new];

它不仅执行任何向它抛出的stringByEvaluatingJavaScriptFromString:,甚至将alert()弹出到桌面!(并不是说这是你想经常做的事情)免责声明:仅在iOS 5+上测试

现在,我有了另一个具有正常网页内容的正常可见的UIWebView,我希望它暂停JavaScript执行:即停止对计时器和DOM事件执行操作。我认为removeFromSuperviewstopLoading以及设置delegate = nil就可以了。但不,只要我将UIWebView添加回某个可见视图,我就可以看到计时器一直在运行。

我理解我的要求的精神错乱。我赞赏它一方面在后台工作(与一些意见相反),但另一方面我想暂停它。但我还是想问一下,是否有任何,甚至是私人的方式可以暂停它。Safari for iOS能够在后台暂停浏览器选项卡。iOS版Chrome不能,这可能是一个可悲的负面证明:(

如果你想找疯子,我有个主意。

我知道暂停JavaScript的唯一方法是显示警报、确认、提示或使用async=false发送ajax请求。

UIWebView被隐藏时,警报是否被隐藏?如果是这样,您可以在希望它冻结时发送警报。当你再次显示视图时,用户将不得不关闭它:

[web stringByEvaluatingJavaScriptFromString:@"alert('Press OK to continue...')"];

或者,您可以通过编程方式将其忽略。我相信你会同意整个建议一定会有麻烦,但这只是一个想法。

您需要完整的UIWebView吗?如果没有,您可以直接调用JavaScriptCore。

- (NSString *)runJS:(NSString *)aJSString 
{
    JSContextRef ctx = JSGlobalContextCreate(NULL); 
    JSStringRef scriptJS = JSStringCreateWithUTF8CString([aJSString UTF8String]);
    JSValueRef exception = NULL;
    JSValueRef result = JSEvaluateScript([self JSContext], scriptJS, NULL, NULL, 0, &exception); 
    JSGlobalContextRelease(ctx);
    ...

这将使您能够更好地控制整个JS运行时,但不幸的是,除了释放整个上下文之外,我还没有找到一个API来暂停定时器的执行。

有关如何使用JavaScriptCore的更完整示例,请参阅https://github.com/jfahrenkrug/AddressBookSpy/blob/master/AddressBookSpy/AddressBookSpy/ABSEngine.m

这听起来可能很明显,但如果你可以在UIWebView中编辑你正在运行的JS,难道你不能在JS中存储一个名为"paused"的全局变量,并在计时器启动时检查一下吗?

var paused = false;
var thread = setInterval(function() {
    if(!paused) {
         // normal timer checking etc
    }
}, 300);

然后,当您删除webView时,只需激发[webView字符串ByEvaluatingJavaScriptFromString:@"paused=true;"],当您将其添加回视图时,设置paused=false。