Не работает API History на iOS? (Адресная строка не обновляется на pushState) - PullRequest
34 голосов
/ 28 мая 2011

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

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

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

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

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

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

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

Ответы [ 5 ]

22 голосов
/ 29 мая 2011

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

Обходной путь - использовать хеш (идентификатор фрагмента) в 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's a hash on the url, try to do something with it
if (location.hash) hashchange();

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

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

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

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

2 голосов
/ 29 мая 2011

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

Начиная с v1.7, здесь исправляются ошибки, которые он исправляет:

  • 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 HTML4 иногда не применяют хэш, если хэш не urlencoded
    • Все браузеры
      • Данные о состоянии и заголовки несохранится после того, как сайт покинет и затем вернется (включая обновления страницы)
      • Названия состояний никогда не применяются к document.title
1 голос
/ 16 августа 2011

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

Если в указанном месте находится символ хеша, адресная строка будет обновлена. Так что это будет работать:

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

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

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

1 голос
/ 29 мая 2011

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

Реми предоставил способ решения этой проблемы в Twitter.

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

0 голосов
/ 28 июня 2011

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

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

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

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

...