Ich weiß, dass der Titel nicht so erklärend ist, aber hier ist die Geschichte: Ich entwickle ein Browsergame, hauptsächlich unter Verwendung von JavaScript und der Mapbox-Bibliothek.
Auf Desktop, Android und iOS funktioniert alles gut, aber unter iOS tritt ein Problem auf: Nachdem das Spiel einige Minuten lang ausgeführt wurde, weist das Telefon plötzlich grafische Artefakte auf und zeigt den größten Teil des verschlüsselten Textes an.
Hier sind einige Fotos, wie das Telefon aussieht:
Meine Frage ist: Was genau in meinem Code kann dies verursachen? Ein Speicherverlust? ( LE : Es stellte sich heraus, dass es sich tatsächlich um einen Speicherverlust handelt.)
Die eigentliche Frage lautet: Wie kommt es, dass Sie fast das gesamte Telefon durch einfaches Durchsuchen einer Webseite blockieren können? Sollte Safari dies nicht stoppen oder zumindest das iOS?
Dies ist bei diesem bestimmten Gerät kein Problem, da dieses Problem auf verschiedenen iPhone-Geräten reproduziert werden kann. (Ich bin mir bei verschiedenen iOS-Versionen nicht so sicher).
Wie ich den Fehler reproduzieren kann:
- Öffne das Spiel (in Safari).
- 3-4 Minuten laufen lassen.
- Schieben Sie das Benachrichtigungscenter nach unten und alles wird verrückt.
Ich habe ein YouTube-Video hinzugefügt, das zeigt, wie ich den Fehler reproduzieren kann (auf meinem iPhone 5C).
Es scheint, dass das Problem zuerst im Benachrichtigungscenter auftritt (wenn Sie das Menü von oben nach unten wischen). Derzeit
scheint dieses Problem nur unteriPhone 5C
iOS 9.2.1 (13D15) aufzutreten. Es tritt auch in der neuen iOS 9.3-Version auf.
Um dieses Problem zu beheben , muss ich:
- Schließen Sie die Safari-Anwendung (in der die Registerkarte "Spiel" geöffnet ist).
- Sperren Sie das Telefon. Nach dem Entsperren ist alles wieder normal.
Einige Details zum Spiel selbst:
- Das Spiel zeigt eine Mapbox-Karte und einige Einheiten darüber (Markierungen).
- Ein Node.js-Server läuft mit 1 Tick / Sekunde und nach jedem Tick wird der aktualisierte Spielstatus über Socket.io an den Browser gesendet.
- Jedes Mal, wenn der Browser den Spielstatus erhält, werden die Markierungen entsprechend aktualisiert.
- * Das Spiel aktualisiert möglicherweise auch Markierungen, wenn Sie hinein- oder herauszoomen oder wenn Sie sie auswählen.
EDIT2:
Speicherverlust festgestellt (wie erwartet). Nach der Behebung dieses Lecks (auf undefined
_icon prüfen ) tritt das Problem nicht mehr auf. Dies bedeutet, dass irgendwo in dieser Richtung der Safari / iOS-Fehler ausgelöst wird.
Hier ist, was genau jeder Tick für jede Einheit genannt wurde, die gruppiert wurde (versteckt und mit anderen in einem MarkerCluster gruppiert wurde):
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);
Und das ist das icons
Array:
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
Der Anruf erfolgt aus dieser Bibliothek: https://github.com/kottenator/jquery-circle-progress
DEMO
Ja, ich konnte eine jsFiddle erstellen, die den Fehler reproduziert: https://jsfiddle.net/cte55cz7/14/ Auf Safari auf dem iPhone 5C öffnen und einige Minuten warten. Auf iPhone 6 und iPad mini stürzt die Seite ab (wie erwartet aufgrund des Speicherverlusts)
Hier ist der gleiche Code in einem HasteBin für alle, die ihn nicht ausführen möchten.
SuperUser
. Ich hoffe, dass dies der richtige Ort ist, um diese Frage zu stellen.Antworten:
Dieser Speicherverlust ist wahrscheinlich darauf zurückzuführen, wie die JS Engine von 'WebKit' funktioniert [safari webkit-javascript llvm]
und sieht wirklich so aus, als wäre es ein Pufferüberlauf im virtuellen Speicher, der sich direkt auf den verbleibenden Arbeitsspeicher auswirkt (gemeinsam genutzt und auch von iOS zum Speichern grafischer Elemente der Benutzeroberfläche verwendet).
Relativ zum Code: "[...] jQuery-Speicherlecks zu finden ist einfach. Überprüfen Sie die Größe von $ .cache. Wenn es zu groß ist, überprüfen Sie es und sehen Sie, welche Einträge bleiben und warum. [...]" ( http://javascript.info/tutorial/memory-leaks )
Lassen Sie mich erwarten, dass es relativ zu dieser for-Schleife ist :
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); }
Angenommen, die Überprüfung ist abgeschlossen, und wenn Sie die Einträge gefunden haben, möchten Sie die Daten möglicherweise manuell mit removeData () bereinigen, oder Sie verwenden zuerst $ elem.detach () und setzen dann $ (elem) .remove () in setTimeout.
quelle