Подтвердить что ты не робот

Является ли API истории нарушенным на iOS? (Строка местоположения не обновляется на pushState)

Подавать это под или Я не могу поверить, что никто не заметил это раньше или я должен был пропустить что-то категории:

Похоже, что если вы делаете простой window.history.pushState в iOS, панель местоположений не обновляется, если она не отвечает на жест пользователя. Само государство начинает толкаться (как вы можете видеть, нажав кнопку кнопки "Назад" ).

Вот самый маленький тестовый сценарий, который я мог бы придумать, чтобы воссоздать проблему:

http://thelink.is/history-api-ios-bug

В настольном браузере, поддерживающем API истории, вы должны увидеть URL-адрес в строке местоположения на /0,/1 и т.д. каждую секунду. На iOS-тестировании с iPhone (под управлением iOS 4.3) и iPad (под управлением iOS 4.3.3) - панель местоположений не обновляется, но нажатие кнопки "Назад" приведет вас к правильному предыдущему местоположению (что будет 404 на тестовом сценарии с нет никакой логики для обработки этих URL-адресов).

Мысли? Обходные? Плечо плакать и обниматься?

ОБНОВЛЕНИЕ: эта проблема была исправлена ​​в iOS 5.

4b9b3361

Ответ 1

Итак, суть в том, что iOS добавила свою собственную безопасность в API истории, что означает, что вы не можете использовать script для изменения URL-адреса. Только действие пользователя может позволить API истории изменить URL-адрес - то есть щелчок - по примеру Aral.

Обходной путь заключается в использовании хэша (aka identifier) ​​на URL-адресе.

Вместо history.pushState мы просто изменим местоположение:

var i = 0;
var locationUpdateInterval = setInterval(function(){
  window.location.hash = i;
  i++;
}, 1000);   

Чтобы зафиксировать событие, когда что-то изменит это местоположение в приложении iOS или если у вас есть постоянная ссылка на конкретную страницу/панель в вашем приложении:

// named function on purpose for later
function hashchange() {
  var pageId = location.hash.substr(1); // drop the # symbol
  // do something with pageId
}

window.onhashchange = hashchange;

// onload - if there a hash on the url, try to do something with it
if (location.hash) hashchange();

Очень плохо, что мы не можем использовать pushState/popState в iOS, но это та же самая защита, что и неспособность запуска полноэкранного видео, если пользователь не инициирует действие, что совпадает с загрузкой видео или аудиоконтент на iOS - вы не можете script его, пользователь должен запустить его (так или иначе).

Как примечание об Android - проблемы довольно похожи, поэтому этот (должен) также работать как обходной путь для Android.

Если вы хотите поддержку на рабочем столе, большинство браузеров поддерживают onhashchange, но, возможно, вы не уверены, что IE не хватает - так что вы можете polyfill плохого мальчика (хотя требуется jQuery...): http://benalman.com/projects/jquery-hashchange-plugin/

Надеюсь, что это поможет.

Ответ 2

Работает отлично для меня при использовании: https://github.com/browserstate/history.js - это также устраняет многие другие ошибки кросс-браузера с API истории HTML5.

Как и в версии 1.1, вот ошибки, которые он решает:

  • History.js решает следующие ошибки браузера:
    • Браузеры HTML5
      • Chrome 8 иногда не содержит правильных данных состояния при переходе в исходное состояние
      • Safari 5, Safari iOS 4 и Firefox 3 и 4 не запускают событие onhashchange, когда страница загружается хешем
      • Safari 5 и Safari iOS 4 не запускают событие onpopstate, когда хэш изменился в отличие от других браузеров
      • Safari 5 и Safari iOS 4 не возвращаются в правильное состояние после замены хеша на replaceState вызов /отчет об ошибке
      • Safari 5 и Safari iOS 4 иногда не могут применять изменение состояния в условиях занятости /отчет об ошибке
      • Google Chrome 8,9,10 и Firefox 4 до RC всегда будут запускать onpopstate после загрузки страницы /изменить рекомендацию
      • В Safari iOS 4.0, 4.1, 4.2 есть рабочий API истории HTML5, хотя фактические обратные кнопки браузеров не работают, поэтому мы рассматриваем их как браузеры HTML4.
      • Ни один из браузеров HTML5 фактически не использует аргумент title для вызовов pushState и replaceState
    • Браузеры HTML4
      • В старых браузерах, таких как MSIE 6,7 и Firefox 2, нет события onhashchange
      • MSIE 6 и 7 иногда не применяют хеш, даже если это было сказано (требуется второй вызов функции apply)
      • Браузеры, не поддерживающие Opera, иногда не применяют хеш, если хэш не urlencoded
    • Все браузеры
      • Данные и названия состояний не сохраняются после того, как сайт оставлен, а затем возвращен (включает обновление страницы)
      • Заголовки состояний никогда не применяются к document.title

Ответ 3

(Обновление: просто увидели, что Remy тоже ответил - вместо этого прочитайте его подробный ответ выше).

Remy предоставил обходной путь для этой проблемы в Twitter.

В принципе, если вы измените location.hash, адрес в строке местоположений обновится. Однако это создает отдельную запись в истории (которая не работает для того, чего я пытаюсь достичь). Обходной путь, который я реализую, - использовать URL-адреса хеширования для iOS и обычные для других платформ, пока ошибка iOS не будет исправлена. Это определенно не идеально, и я надеюсь, что Mobile Safari на iOS начнет вести себя как Chrome, Firefox и Safari на рабочем столе.

Ответ 4

Вот что я нашел:

Когда вытолкнутое местоположение содержит хеш-символ, адресная панель будет обновлена. Итак, это сработает:

window.history.pushState(data, title, 'a/new/url#');

Но объект window.location не будет обновлен, поэтому вам нужно сохранить задвинутый URL-адрес в переменную и использовать это вместо window.location, если вам нужно толкаемое местоположение.

Протестировано в Safari для Android.

Ответ 5

Я нашел хак, который работает. Оказывается, если вы измените хэш сразу после history.pushState, панель адресов будет обновлена. Как:

        window.history.pushState(data, title, 'a/new/url');
        window.location.hash = 'new';

изменяет строку местоположения на http://example.com/a/new/url#new. Это вводит другую проблему, потому что хеш становится ее собственной записью истории. Поэтому вам все равно нужно слушать onHashChange.

Это немного сложно, но есть люди, которые действительно, действительно ненавидят хешбанговые URL-адреса и очень громко говорят об этом. Так что это того стоит.