如何在屏幕解锁后恢复iOS8网络应用上的JavaScript计时器?

时间:2014-09-24 04:00:53

标签: javascript html5 ios8

在iOS8上,这个HTML5网络应用程序在屏幕被锁定后不会恢复js计时器,如果webapp处于活动状态并且从主屏幕图标启动,则会解锁。在iOS7上,计时器将在这种情况下继续。我需要在屏幕解锁后继续计时器 - 任何实现此目的的提示?

注意/请首先使用Safari"添加到主屏幕"将Web应用程序添加到主屏幕。通过分享按钮。在Safari中运行页面不会导致上述问题。

<html>
<head>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <title>Test</title>
    <script>
        var tim;
        function go() {
            tim = window.setInterval(action, 1000);
        }
        function action() {
            document.getElementById('x').innerHTML = new Date().getTime().toString();
        }
    </script>
</head>
<body onload="go()">
    <div id="x"></div>
</body>
</html>

7 个答案:

答案 0 :(得分:5)

我们最终解决的解决方案并未解决IOS8中睡眠模式后的所有损坏功能,而只是ajax requests / setTimeout / setInterval / requestAnimationFrame及其各自的清除功能。

睡眠模式后破坏的其他事情:

  • -webkit-transition opacity导致不可选区域
  • 在键盘打开时调用的worker.postMessage永久杀死所有WebWorkers
  • 窗口弹跳/平移可以杀死所有WebWorkers。
  • overflowchange / resize事件不再有效。你需要修改任何依赖于它们的逻辑。

制作半工作解决方案:

  1. 覆盖setTimeout / setInterval / requestAnimationFrame / clearInterval / clearTimeout / cancelAnimationFrame。所有这些函数都需要postMessage到webworker,webworker将相应地执行setTimeout / setInterval。您可能还需要为这些功能设置暂停机制,但我并非100%必要。
  2. 覆盖XMLHttpRequest,以便在调用send时,实际上是在webworker上执行请求。
  3. 为所有网络工作者创建一个暂停机制,以便主线程可以确定所有网络工作者何时刷新了他们的消息(基本上需要防止在键盘启动时调用任何工作人员调用postMessage)。
  4. 防止键盘弹出可编辑元素。在可编辑元素上检测到点击/点击事件后,您需要手动调用焦点功能。
  5. 在打开键盘的可编辑元素上覆盖焦点功能。焦点现在将调用暂停工作器功能。暂停所有工作人员后,调用浏览器实施焦点。
  6. 将focusout事件侦听器添加到可编辑元素,以便调用resume workers函数。
  7. 我的github上有一个半抽象版本可供其他人使用。我们在相当复杂/大型且大量动画+ ajax相关的应用程序中使用github版本,几乎没有问题。

    https://github.com/TaDaa/IOS8-FIX

答案 1 :(得分:4)

安装iOS 8.1.1修复了这个问题

答案 2 :(得分:3)

以下是我的工作解决方案的示例。

工人脚本backgrond.js

setInterval(function () {
    postMessage(JSON.stringify({
        message: "tiktok",
        result: new Date().getTime()
    }));
}, 500);

页面脚本 - 编辑后的评论2014-10-30

var GUI = {
    iOS8: false,
    web_worker: null,
    tik: new Date().getTime(),
    tok: new Date().getTime(),
    init: function(){
        GUI.web_worker = new Worker("scripts/background.js");
        GUI.web_worker.onmessage = function (event) {
            var d = JSON.parse(event.data);
            if (d.message === 'tiktok') {
                GUI.tik = d.result;
                if (Math.abs(GUI.tik - GUI.tok) > (15 * 1000) && GUI.iOS8 ) {
                    GUI.web_worker.terminate();
                    document.write('Please restart app after locking the screen.  Apple are working to prevent this issue.');
                 }
            };
        }
        setInterval(function () { GUI.tok = new Date().getTime(); }, 1000);
        var ua = navigator.userAgent.toLowerCase();
        GUI.iOS8 = ua.indexOf("os 8_0") !==-1 || ua.indexOf("os 8_1") !==-1;
  }
}

GUI.init();

答案 3 :(得分:0)

对于Ajax请求的另一种解决方法(涉及服务器端工作)但在此处工作:iOS 8 Bug - OnUpdateReady never called again when device returns from sleep

答案 4 :(得分:0)

我尝试了修复,但它在iphone4s和IOS8上无效。

我在我的版本手机上发现一个警告框在你锁定并退出后崩溃了应用程序......基本上我放了一个警告框说当关闭并重​​新启动应用程序时,当settimeout计时器停止使用屏幕更新时onlclick ... SOoo Messy ......这是一个可怕的错误!

答案 5 :(得分:0)

它已在iOS 8.1.3上修复。

我正在使用EaselJS库,它在内部使用requestAnimationFrame或setTimeout来更新tick。它在iOS 8.0.x上有同样的问题,但它已在iOS 8.1.3上修复。

答案 6 :(得分:-1)

假设每次手机解锁时都会处理window.onload事件,请尝试以下操作:

window.onload = function() { window.location.reload() }

由于我目前没有设备来测试此功能,因此这只是一个盲目猜测。希望这对你有用。