检测iOS Webclip启动时如何解决iOS 13 Bug

4

背景

我把全屏web应用程序安装到iOS设备的主屏幕上,并在每次启动web应用程序时运行一些javascript

苹果在iOS 13中进行了更改,使得脚本仅在第一次启动时运行。每次启动都会呈现从上次离开的地方开始的web应用程序(除非它已从应用切换器中删除)。

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

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

以下是问题所在...

iOS 13还引入了一个错误,我已经报告了,但似乎不会很快修复,并且在13GM和13.1 beta中仍然存在。

错误

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

问题

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

编辑

按照要求,以下是示例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>
1个回答

1

你能尝试或已经尝试过吗:

 function  isPageHidden(){
 return document.hidden; //document.visibilityState == 'hidden'
  }

window.addEventListener("focus", function(event) 
 { 
   If(!isPageHidden())
   // do something
   }, false);

or

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 
    }

我刚刚测试了这个,它表现得非常奇怪。首先,在打开Web应用程序的第一次时不起作用,但之后每次都会起作用,然而一旦我打开另一个Web应用程序并返回到这个应用程序时,它就不起作用了。 - Darren
一样。当打开另一个Web应用程序时,document.hidden似乎也会返回false :( - Darren
和 document.visibilityState == 'hidden'? - Oleg
我的使用情况可能会持续很长一段时间。我使用js通过URL方案启动应用程序,因此稍后启动新应用程序的用户将导致之前启动的应用程序再次启动。 - Darren
尝试在visibilitychange事件中验证document.title是否已更改,并使用Event.stopPropagation(),Event.stopPropagation()和Event.preventDefault()来跟踪事件的顺序。 - Oleg
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接