【问题标题】:Detecting when iOS Webclip is launched whilst working around an iOS 13 bug在解决 iOS 13 错误时检测何时启动 iOS Webclip
【发布时间】:2026-01-19 09:15:01
【问题描述】:

背景

我将全屏网络应用程序安装到 iOS 设备的主屏幕上,并在每次启动网络应用程序时运行一些 javascript。 Apple 在 iOS 13 中进行了更改,脚本仅在首次启动时运行。每次后续启动都会从上次停止的地方显示 Web 应用,而不会刷新到开始处(除非它已从应用切换器中删除)。

我相信这是 Web App 开发人员非常需要的功能,可以在用户切换到另一个应用程序并再次返回时停止网页刷新

为了让javascript在每次应用程序被带到前台或启动时运行一些代码,我想我可以简单地使用一些通知来查看focusblurvisibilitychange或者查看document.activeElement , document.hasFocus()document.hidden.

这就是问题所在......

iOS 13 还引入了我报告的一个错误,但看起来它不会很快得到修复,并且仍然存在于 13GM 和 13.1 测试版中。

错误

如果您有多个主屏幕网络应用程序,就好像它们都共享同一个网络容器。启动第二个 Web 应用程序会导致所有焦点类型通知在之前打开的 Web 应用程序上触发,就好像它们再次成为前面和中心一样。这意味着任何javascript 代码都将像已启动一样运行,即使它没有启动。

问题

我正在尝试找到解决此错误的方法,并在 Web 应用程序在前端和中心启动时收到通知。使用 onLoad 类型代码只会在 Web 应用程序留在应用程序切换器中时运行一次。在启动其他 Web 应用程序时,观看 focus 类型的事件将不必要地触发。有没有我可以尝试调用的其他事件或方法,或者我可以尝试实现的任何技巧?

编辑

根据要求,这里是示例 html:

<html>
<head>
    <title>visibilitychange</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
</head>
<body id="body">
    <h1>visibilitychange</h1>
    <h3>Save this web clip to your home screen, then when you open it it'll automatically list the times the visibilitychange notification is called and the state</h3>
    <br /><br />

    <p>Initial page visibility was <b id="status">unknown</b>.</p>
    <div id="target"></div>

    <script type="text/javascript">
        document.getElementById('status').innerHTML = document.hidden ? 'hidden' : 'visible';

        var target = document.getElementById('target');
        function logToScreen(text) {
            var timeBadge = new Date().toTimeString().split(' ')[0];
            var newState = document.createElement('p');
            newState.innerHTML = '<span class="badge">' + timeBadge + '</span> ' + text + '</b>';
            target.appendChild(newState);
        }

        function isPageHidden() {
            console.log('isPageHidden() ==' + document.visibilityState);
            logToScreen('isPageHidden() ==' + document.visibilityState);
            return document.visibilityState == 'hidden'; // document.hidden;
        }

        document.addEventListener("visibilitychange", function(event) 
        {
            console.log('visibilitychange event listener');
            logToScreen('visibilitychange event listener');
            if(!isPageHidden()) {
                console.log('page opened');
                logToScreen('page opened');
            }
        }, false);
    </script>
</body>
</html>

【问题讨论】:

    标签: javascript ios dom mobile-safari ios13


    【解决方案1】:

    你能试试吗:

     function  isPageHidden(){
     return document.hidden; //document.visibilityState == 'hidden'
      }
    
    window.addEventListener("focus", function(event) 
     { 
       If(!isPageHidden())
       // do something
       }, false);
    

    document.addEventListener('visibilitychange', function(){
         If(!isPageHidden())
           // do something
           }, false);
    });
    

    另一种解决方法是:将执行操作的最后时间戳保存在本地存储中,如果已达到执行 javascript 运行任务的间隔,则检查相关事件(焦点、模糊、可见性)。

    更新:

    window.addEventListener('locationchange', function(){
        console.log('location changed!');
       //check current location.pathname
    })
    

      window.onhashchange = function() { 
             console.log('location changed!');
           //check current location.pathname 
        }
    

    【讨论】:

    • 我刚刚测试了这个,它的行为真的很奇怪。首先,它不会在第一次打开网络应用程序时触发,但之后每次都会触发,但是一旦我打开另一个网络应用程序并回到这个,它根本不会触发。
    • visibilitychange 事件怎么样?我编辑了答案
    • 相同。当打开另一个网络应用程序时,document.hidden 似乎也会返回 false :(
    • and document.visibilityState == 'hidden'?
    • Same :( 我认为 iOS 13 中的错误是将所有 Web 应用程序视为使用相同的容器并可能在它们之间共享相同的变量。