Development Tip

Safari 페이지가 iOS 렌더링을 중단하는 이유는 무엇입니까?

yourdevel 2020. 10. 10. 12:08
반응형

Safari 페이지가 iOS 렌더링을 중단하는 이유는 무엇입니까?


제목이 그다지 설명 적이 지 않다는 것을 알고 있지만 여기에 이야기가 있습니다. 주로 JavaScript와 Mapbox 라이브러리를 사용하여 브라우저 게임을 개발하고 있습니다.

데스크톱, Android 및 iOS에서는 모든 것이 잘 작동하지만 iOS에서는 한 가지 문제가 나타납니다. 게임을 몇 분 동안 실행 한 후 갑자기 전화에 그래픽 아티팩트가 나타나고 대부분의 텍스트가 뒤섞여 표시됩니다.

다음은 휴대 전화가 시작되는 모습에 대한 사진입니다. 여기에 이미지 설명 입력 여기에 이미지 설명 입력 여기에 이미지 설명 입력

내 질문 은 : 정확히 내 코드에서 이것이 발생할 수 있습니까? 메모리 누수? ( LE : 실제로 메모리 누수로 밝혀졌습니다.)
진짜 질문 은 어떻게하면 단순히 웹 페이지를 검색하는 것만으로 휴대폰 전체를 거의 브릭 킹 할 수 있다는 것입니다. 사파리가 이걸 막아야하지 않나요? 아니면 적어도 iOS 는요?

이 문제는 다른 iPhone 장치에서 재현 될 수 있으므로이 특정 장치의 문제가 아닙니다. (다른 iOS 버전에 대해 잘 모르겠습니다).

오류를 재현 하는 방법 :

  1. 게임을 엽니 다 (Safari 내부).
  2. 3-4 분 동안 실행합니다.
  3. 알림 센터를 아래로 내리면 모든 것이 미쳐 버립니다. iPhone 5C에서 오류를 재현하는 방법을 보여주는 YouTube 비디오
    추가했습니다 . 알림 센터에 문제가 처음 나타나는 것 같습니다 (상단에서 메뉴를 아래로 스 와이프 한 경우). 현재이 문제는 iOS 9.2.1 (13D15) 에서만 발생하는 것 같습니다 . 새로운 iOS 9.3 버전에서도 발생합니다.

    iPhone 5C

이 문제 해결 하려면 다음을 수행 해야합니다.

  1. 게임 탭이 열려있는 Safari 응용 프로그램을 닫습니다.
  2. 전화를 잠급니다. 잠금을 해제하면 모든 것이 정상으로 돌아갑니다.

게임 자체 에 대한 세부 정보 :

  1. 이 게임은 Mapbox 맵과 그 위에 일부 유닛 (마커)을 보여줍니다.
  2. Node.js 서버는 1 틱 / 초로 실행되며 각 틱 후에 업데이트 된 게임 상태가 Socket.io를 통해 브라우저로 전송됩니다.
  3. 브라우저가 게임 상태를 수신 할 때마다 그에 따라 마커를 업데이트합니다.
  4. * 확대 또는 축소하거나 마커를 선택하면 게임에서 마커를 업데이트 할 수도 있습니다.

EDIT2 : 예상대로 메모리 누수를 발견했습니다. 이 누수를 수정 한 후 ( undefined_icon 확인 ) 문제가 더 이상 발생하지 않습니다. 즉, 해당 라인 어딘가에서 Safari / iOS 버그가 트리거됩니다.

다음은 클러스터 된 각 단위에 대해 정확히 각 틱이라고 부르는 것입니다 (숨겨지고 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);

And this is the 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 call is from this library: https://github.com/kottenator/jquery-circle-progress

DEMO

Yay, I have been able to create a jsFiddle that reproduces the bug: https://jsfiddle.net/cte55cz7/14/ Open on Safari on iPhone 5C and wait a couple of minutes. On iPhone 6 and iPad mini the page crashes (as expected due to the memory leak)

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


This memory leaks is probably due to how 'WebKit’s JS Engine' works [safari webkit-javascript llvm]

and really looks like to be a virtual memory buffer-overflow, having a direct impact on the remaining RAM (shared and used also by iOS to store User Interface graphical elements)

코드 조각과 관련하여 : "[...] jQuery 메모리 누수를 찾는 것은 쉽습니다. $ .cache의 크기를 확인하십시오. 크기가 너무 크면 검사하고 어떤 항목이 남아 있는지 확인하십시오. [...]"( http://javascript.info/tutorial/memory-leaks )

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);
}

검사가 완료되었다고 가정하고 항목을 찾았다 고 가정하면 removeData ()를 사용 하여 데이터를 수동으로 정리 하거나 먼저 $ elem.detach () 를 사용한 다음 $ (elem) .remove ()를 입력 할 수 있습니다. setTimeout에서.

참고 URL : https://stackoverflow.com/questions/35782231/why-is-a-safari-page-breaking-ios-rendering

반응형