Есть ли ошибка с использованием InnerHTML внутри UIWebView в собственном приложении iPhone? - PullRequest
10 голосов
/ 03 января 2011

У меня довольно большое приложение HTML / JS / CSS, которое отлично работает при запуске в качестве веб-приложения с Safari на iPhone.

При запуске этого же приложения в UIWebView в собственном приложении iPhone вызовы в jQuery для создания фрагментов HTML молча завершаются неудачей (т. Е. $("<div>HELLO WORLD</div>"); не создает элемент.

Я отследил это до следующего эквивалентного фрагмента кода в чистом методе jQuery:

var div = document.createElement(“div”); div.innerHTML = “<div>HELLO WORLD</div>”;

Когда я смотрю на div.outerHTML, я вижу <div>/<div>

div.innerHTML возвращает пустую строку.

Это, похоже, не проблема jQuery и не происходит в 100% случаев. Я не смог найти шаблон, но в некоторых случаях он работает 2-3 раза подряд, иногда, если происходит сбой 5-6 раз подряд. Кажется, это проявляется только при запуске приложения внутри UIWebView в приложении Objective-C. Также я видел это только на реальном устройстве под управлением iOS 4.2, а не на эмуляторе.

Кто-нибудь сталкивался с чем-нибудь подобным? У кого-нибудь есть починка?

Ответы [ 3 ]

5 голосов
/ 05 января 2011

У меня тоже были такие проблемы. Это происходит, когда процессор телефона очень занят (скажем, 100%). Тогда механизм рендеринга иногда забывает о настройках innerHTML.

Решение, включенное в мой унифицированный проект , заключается в проверке наличия элемента в childNodes, в противном случае примените его снова.

var target = document.createElement("div");
var text = "<div>Hello World</div>";
target.innerHTML = text;
var self = this;
self.__intervalHandle = window.setInterval(function() {
  target.innerHTML = text:
  if (target.firstChild) {
    window.clearInterval(self.__intervalHandle);
    self.__intervalHandle = null;
  }
}, 100);

Это заставляет механизм рендеринга применять innerHTML к DOM и дает механизму рендеринга некоторое время (100 мс в этом примере, хорошее значение в наших тестах) для его обработки.

2 голосов
/ 13 апреля 2011

Вы должны взглянуть на http://blog.techno -barje.fr / post / 2010/10/06 / UIWebView-secrets-part3-Как правильно вызвать ObjectiveC-from-Javascript .

Оказывается, что отмена навигации как часть метода делегата -webView:shouldStartLoadWithRequest: может вызвать проблемы с innerHTML.Я обновил наш JS-код, чтобы использовать метод, рекомендованный в этой статье, и я не видел, чтобы какое-то время возникала проблема innerHTML.

2 голосов
/ 25 февраля 2011

Что ж, решение [НЕ решение по качеству производства], опубликованное Себастьяном, сработало, но я не мог подтвердить, будет ли загрузка процессора причиной этой проблемы.Я сгенерировал много фоновой нагрузки на хосте iOS и не смог воспроизвести эту проблему.

После дальнейшего изучения проблема рендеринга, похоже, является побочным эффектом оболочки iOS, отменяющей навигацию.Как только навигация iOS отменяется, ядро ​​рендеринга, вероятно, воспримет это как не нужное для рендеринга большего количества пользовательского интерфейса [в основном ничего не рендерится в течение небольшого периода].

Один из способов исправить это -отправлять команды в оболочку iOS в виде параметров хеша (#) вместо URL.Таким образом, оболочка iOS будет получать команды и не должна отменять навигацию.Этот подход, кажется, работает в тестовом коде ниже.Таким образом, если window.location установлен в location1, он выдает предупреждение «At: 1», а элемент e2 не имеет значения.И если для window.location задано значение location2, оно предупреждает «At: 0», а элемент e2 имеет значение.

@ Кевин, не могли бы вы подтвердить, что вы отменяли навигацию на хосте iOS, когда это произошло.

Тестовый код:

Javascript:

    var location1 = "myApp://Test";
    var location2 = "#myApp://Test";
    $("#change").live("click", function (e) {
        var element = document.getElementById("e1");
        window.location = location1; var i = 0;            
        element.innerHTML = "At: " + i;
        window.__intervalHandle = window.setInterval(function () {
            var html = element.innerHTML;
            if (html) {
                 alert(html);
                window.clearInterval(window.__intervalHandle);
                window.__intervalHandle = null;
            } else {
                element.innerHTML = "At: " + ++i;
            }
        }, 1);
        document.getElementById("e2").innerHTML = "Test";
    });

Псевдокод iOS:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL* u = [ request URL];

if( [[u scheme] compare:@"myapp" ] == NSOrderedSame) {
{ 
return NO; // don’t navigate
}
return YES; // navigate
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...