javascript - habilitar - ¿Por qué una página de Safari rompe el renderizado de iOS?
como activar javascript en safari iphone (1)
Sé que el título no es tan explicativo, pero aquí está la historia: estoy desarrollando un juego de navegador, principalmente usando JavaScript y la biblioteca Mapbox.
Todo funciona bien en computadoras de escritorio, Android e iOS, pero aparece un problema en iOS: después de dejar que el juego se ejecute durante unos minutos, el teléfono de repente comienza a tener artefactos gráficos y muestra la mayor parte del texto codificado.
Aquí hay algunas fotos de cómo se ve el teléfono:
Mi pregunta
es: ¿qué puede causar esto exactamente en mi código?
¿Una pérdida de memoria?
(
LE
: resultó ser realmente una pérdida de memoria)
La verdadera pregunta
es: ¿cómo es que casi puedes bloquear todo el teléfono simplemente navegando por una página web?
¿No debería Safari detener esto, o al menos el iOS?
Esto no es un problema con este dispositivo específico, ya que este problema puede reproducirse en diferentes dispositivos iPhone. (No estoy tan seguro acerca de las diferentes versiones de iOS).
Cómo puedo reproducir el error:
- Abre el juego (dentro de Safari).
- Déjalo correr por 3-4 minutos.
-
Deslice hacia abajo el centro de notificaciones y todo se vuelve loco.
He agregado un video de YouTube que muestra cómo puedo reproducir el error (en mi iPhone 5C).
Parece que el problema aparece por primera vez en el centro de notificaciones (si desliza hacia abajo el menú desde la parte superior).
Por ahora, este problema parece ocurrir solo eniPhone 5C
iOS 9.2.1 (13D15). También ocurre en la nueva versión iOS 9.3.
Para solucionar este problema, tengo que:
- Cierre la aplicación Safari (en la que está abierta la pestaña del juego).
- Cierra el teléfono. Después de desbloquearlo, todo vuelve a la normalidad.
Algunos detalles sobre el juego en sí:
- El juego muestra un mapa Mapbox y algunas unidades sobre él (marcadores).
- Un servidor Node.js se ejecuta a 1 tic / segundo y después de cada tic el estado del juego actualizado se envía al navegador a través de Socket.io.
- Cada vez que el navegador recibe el estado del juego, actualiza los marcadores en consecuencia.
- * El juego también puede actualizar los marcadores si acercas o alejas o si los seleccionas.
EDIT2:
Encontró la pérdida de memoria (como se esperaba).
Después de corregir esta fuga (verifique si hay
undefined
ícono
undefined
), el problema ya no se produce.
Esto significa que en algún lugar a lo largo de esas líneas se activa el error Safari / iOS.
Esto es lo que exactamente se llamaba cada tic, para cada unidad que estaba agrupada (estaba oculta y agrupada con otras dentro de un MarkerCluster):
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);
Y esta es la matriz de
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
llamada
circleProgress
es de esta biblioteca:
https://github.com/kottenator/jquery-circle-progress
MANIFESTACIÓN
Sí, he podido crear un jsFiddle que reproduce el error: https://jsfiddle.net/cte55cz7/14/ Abra en Safari en el iPhone 5C y espere un par de minutos. En iPhone 6 y iPad mini, la página se bloquea (como se esperaba debido a la pérdida de memoria)
Aquí está el mismo código en un HasteBin, para cualquiera que no quiera ejecutarlo.
Esta pérdida de memoria probablemente se deba a cómo funciona el ''Motor JS de WebKit'' [safari webkit-javascript llvm]
y realmente parece ser un desbordamiento de búfer de memoria virtual, que tiene un impacto directo en la RAM restante (compartida y utilizada también por iOS para almacenar elementos gráficos de la interfaz de usuario)
Relativamente al fragmento de código: "[...] encontrar fugas de memoria jQuery es fácil. Verifique el tamaño de $ .cache. Si es demasiado grande, inspecciónelo y vea qué entradas quedan y por qué". http://javascript.info/tutorial/memory-leaks )
Déjame esperar que sea relativo a este bucle for :
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);
}
Suponiendo que se realiza la inspección, y también asumiendo el hecho de que encuentra las entradas, es posible que desee limpiar los datos manualmente con removeData () o puede usar primero $ elem.detach () y luego poner $ (elem) .remove () en setTimeout.