为什么Safari页面会破坏iOS渲染?

时间:2016-03-03 20:21:17

标签: javascript ios iphone safari artifacts

我知道标题不是那么解释,但这是故事:我正在开发一个浏览器游戏,主要是使用JavaScript和Mapbox库。

在台式机,Android和iOS上一切运行良好但在iOS上出现一个问题:让游戏运行几分钟后,手机突然开始出现图形文物,并显示大部分文字都在乱码。

以下是一些手机开始时的照片: enter image description here enter image description here enter image description here

我的问题是:我的代码中究竟是什么原因引起的?内存泄漏? ( LE :事实证明它实际上是内存泄漏)
真正的问题是:如何通过简单地浏览网页来完成整个手机的操作? Safari不应该阻止这个,或者至少是iOS?

这个特定设备不是问题,因为这个问题可以在不同的iPhone设备上重现。 (我对不同的iOS版本不太确定。)

我如何重现错误:

  1. 打开游戏(在Safari中)。
  2. 让它运行3-4分钟。
  3. 向下滑动通知中心,一切都变得疯狂 我添加了一个YouTube video,显示我如何重现错误(在我的iPhone 5C上) 似乎问题首先出现在通知中心(如果您从顶部向下滑动菜单) 至于现在,这个问题似乎只发生在iPhone 5C iOS 9.2.1(13D15)上。它也出现在新的iOS 9.3版本上。
  4. 为了修复这个问题,我必须:

    1. 关闭Safari应用程序(游戏选项卡已打开)。
    2. 锁定手机。解锁后一切恢复正常。
    3. 游戏本身的一些细节:

      1. 游戏显示一个Mapbox地图及其上的一些单位(标记)。
      2. Node.js服务器以1 tick /秒的速度运行,每次滴答后,更新的游戏状态将通过Socket.io发送到浏览器。
      3. 每次浏览器收到游戏状态时,都会相应地更新标记。
      4. *如果您放大或缩小游戏或选择它们,游戏也可能会更新标记。
      5. EDIT2: 发现内存泄漏(如预期)。修复此泄漏(检查undefined _icon)后,问题不再发生。这意味着,在这些行的某处,触发了Safari / iOS错误。

        对于每个聚集的单元(隐藏在MarkerCluster中并与其他单元组合在一起),以下是每个tick的确切调用内容:

            var $icon = $(marker._icon); // marker._icon is undefined because of the clustering
        
            $icon.html('');
        
            $icon.append($('<img class="markerIcon" src="' + options.iconUrl + '" />'));
        
            var iconX = 10;
            var iconY = -10;
            var iconOffset = 0;
        
            for(var v in this.icons) {
                this.icons[v].css('z-index', + $icon.css('z-index') + 1);
                this.icons[v].css('transform', 'translate3d(' + iconX + 'px,' 
                                        + (iconY + iconOffset) + 'px,' + '0px)');
                iconOffset += 20;
        
                this.icons[v].appendTo($icon);
            }
        
            // Fire rate icons
            this.attackRateCircle = $('<div class="circle"></div>');
            this.attackRateCircle.circleProgress({
                value: 0,
                size: 16,
                fill: { color: "#b5deff" },
                emptyFill: 'rgba(0, 0, 0, 0.5)',
                startAngle:  -Math.PI / 2,
                thickness: 4,
                animation: false,
            });
            this.attackRateCircle.hide();
        
            // Create and display the healthbar
            this.healthBar = $('<div>').addClass('healthBar ');
            this.healthBar.css('z-index', $icon.css('z-index'));
            this.healthBarFill = $('<span class="fill">');
            this.healthBar.append(this.healthBarFill);
        
            $icon.append(this.healthBar);
            $icon.append(this.attackRateCircle);
        

        这是icons数组:

        this.icons = {
            attack_order: $('<img src="img/attack.png" class="status_icon">'),
            attack: $('<img src="img/damage.png" class="status_icon icon_damage">'),
            hit: $('<img src="img/hit.png" class="status_icon icon_hit">'),
        };
        

        circleProgress来自此库的电话:https://github.com/kottenator/jquery-circle-progress

        样本

        是的,我已经能够创建一个重现错误的jsFiddle:https://jsfiddle.net/cte55cz7/14/ 在iPhone 5C上的Safari上打开并等待几分钟。在iPhone 6和iPad mini上,页面崩溃(正如预期的那样由于内存泄漏)

        Here's the same code in a HasteBin, for anyone who doesn't want to run it.

1 个答案:

答案 0 :(得分:1)

这个内存泄漏可能是由于'WebKit的JS引擎'的工作原理[safari webkit-javascript llvm]

并且真的看起来像是一个虚拟内存缓冲区溢出,对剩余的RAM有直接影响(iOS共享和使用它来存储用户界面图形元素)

相对于这段代码: “[...]查找jQuery内存泄漏很容易。检查$ .cache的大小。如果它太大,请检查它,看看哪些条目保留,为什么。[...]”(http://javascript.info/tutorial/memory-leaks)< / p>

我希望它与 for loop

相关
for(var v in this.icons) {
    this.icons[v].css('z-index', + $icon.css('z-index') + 1);
    this.icons[v].css('transform', 'translate3d(' + iconX + 'px,' 
                            + (iconY + iconOffset) + 'px,' + '0px)');
    iconOffset += 20;

    this.icons[v].appendTo($icon);
}

假设检查完成,并且假设您找到了条目,您可能希望使用 removeData()手动清理数据 或者您可以先使用 $ elem.detach(),然后在setTimeout中输入 $(elem).remove()