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

IOS "Веб-приложение" имеет разные локальные хранилища, чем Mobile Safari

У меня есть webapp для iPad с метатегами:

<meta name="apple-mobile-web-app-capable" content="yes">

Когда я открываю приложение с домашней страницы (версия, поддерживающая веб-приложение) или набираю адрес в Mobile Safari, содержимое localStorage отличается. Я подтвердил, что адреса идентичны, напечатав location.href.

Все изменения, внесенные в localStorage при использовании Safari для мобильных устройств, отражаются в версии, поддерживающей веб-приложение, но изменения, внесенные в версию, поддерживающую веб-приложение, не отражаются в версии Mobile Safari.

Домены идентичны, localStorage должен быть идентичным. Что происходит в мире? Можно ли это исправить?


Обновление - решение. Следуя предложению № 2 от принятого ответа (заставляя пользователя находиться в полноэкранном режиме), я добавил этот бит кода:

if(("standalone" in window.navigator) && !window.navigator.standalone)
    window.location = "instructions.html";

Итак, если вы используете браузер, поддерживающий автономный режим, и вы не находитесь в автономном режиме, перенаправляйтесь на страницу (instructions.html), которая показывает пользователю, как добавить приложение на главный экран.

Спасибо всем за их вклад!

4b9b3361

Ответ 1

Резюме:

Safari и полноэкранные веб-приложения (с поддержкой веб-приложений a.k.a.) имеют отдельные кэши для записи в памяти данных localStorage. Каждый раз, когда полноэкранное приложение становится активным, он перезагружает localStorage с диска (позволяя ему видеть изменения Safari). Однако, когда Safari становится активным, он не перезагружает данные localStorage с диска, поэтому он не будет видеть изменений, внесенных в полноэкранное приложение, если вы не убьете Safari и не перезапустите его.

Полное объяснение:

В информатике есть только две проблемы:

  • недействительность кэша
  • Именование вещей
  • ошибки "один за другим"

Ошибочное поведение в localStorage является результатом проблемы №1. Вот почему:

Когда движок браузера iOS загружается, он считывает данные для localStorage с диска и кэширует его в памяти. Затем каждый раз, когда вы читаете данные (например, getItem), данные считываются из памяти, а не из диска; и при записи (например, setItem) данные записываются в память, а затем (асинхронно) сбрасываются на диск. Поскольку localStorage является синхронным, эта реализация является вполне разумной. Если бы он перешел на диск для всех чтений и записей, ваш javascript был бы заблокирован при каждом чтении/записи для выполнения дорогостоящего ввода-вывода.

Проблема заключается в том, что полноэкранное веб-приложение (пусть оно называется FSWA) использует отдельный экземпляр механизма браузера iOS, и хотя FSWA использует то же местоположение на диске для данных localStorage, поделитесь кешем в памяти данных localStorage с Safari.

Когда вы добавляете тот факт, что FSWA полностью перезагружается (что означает, что данные локального хранилища перезагружаются с диска) каждый раз, когда они становятся активным приложением, вы получаете поведение, которое вы видите.

Вот за кулисами...

  • пользователь производит изменение, которое записывает данные в localStorage в Safari
  • Safari записывает данные в кеш-память localStorage в хранилище Safari
  • Safari очищает данные localStorage от кеша на диске
  • пользователь покидает сафари и запускает FSWA
  • FSWA загружает и считывает данные localStorage с диска в кеш-память
  • пользователь видит данные, которые были изменены (в шаге # 1) в Safari
  • пользователь вносит изменения в FSWA, который записывает данные в localStorage
  • FSWA записывает данные в свой кэш localStorage (кеш Safari не обновляется)
  • FSWA сбрасывает свои данные кэша localStorage на диск
  • пользователь переключается обратно в Safari
  • Safari уже запущен, и он не перезагружает данные localStorage с диска
  • Safari считывает старые данные из существующего кэша в памяти
  • Пользователь не видит изменений, сделанных на шаге 7

Чтобы доказать это, вы можете убить Safari между шагами # 4 и шагом # 10. Затем, когда вы перезапустите Safari на шаге 11, он перезагрузит localStorage с диска, и вы увидите данные, написанные FSWA.

Ответ 2

В iOS5 я смог иметь два полноэкранных веб-приложения в том же домене, которые могли видеть друг друга localStorage. Это преодолело разницу между полноэкранным и Safari.

Однако с iOS6 мне нужно объединить два моих полноэкранных веб-приложения в одно приложение.

Ответ 3

Предполагая, что вы правильно сохраняете данные локального хранилища, и если я не ошибаюсь, то, что вы испытываете, - это некоторая общая проблема среди разработчиков веб-приложений. Куки файлы, сеансы и локальное хранилище, по-видимому, хранятся по-разному в "веб-приложении" (запущенном с рабочего стола) до данных, сохраненных с помощью мобильного сафари.

Я провел несколько довольно тщательных тестов в прошлом и , мне кажется, что обходного пути недостаточно.. Просто чтобы привести пример, с которым мы с коллегами столкнулись с подобной проблемой: в веб-приложении, которое мы разработали недавно, пользователь должен войти в систему, прежде чем обращаться ко всем его функциям. Если вы входите в систему с помощью мобильного сафари, а затем переключитесь на загруженную версию приложения, ожидается, что он войдет в систему, но это не всегда так. Как правило, нужно снова войти в систему, предлагая, чтобы файлы cookie могли храниться в разных "банках данных" в зависимости от того, как или откуда вы хотите запустить приложение.

Кроме того, как говорит Кальвин, в этом есть нечто большее, чем просто разные банки данных. Службы, запущенные с помощью домашнего экрана, появляются медленнее, домашние приложения всегда перезагружаются при запуске, предлагая поддержку нескольких задач и т.д. Мой вывод: программа запускает загруженные веб-приложения!= Сафари минус адресная строка и, следовательно, не должна быть считаются таковыми.

Несмотря на отличную функциональность Apple, домашние веб-приложения не работают так, как ожидалось, или, как можно было бы надеяться (например, как это было открыто в сафари). В вашем случае, если вы правильно храните данные LS и пробовали разные подходы чтобы исправить вашу конкретную проблему, Я бы предложил одну из следующих альтернатив:

  • Используйте базу данных mysql для r/w из/вместо
  • Заставить пользователей загружать приложение перед его использованием (например, этот пример)
  • Не поощряйте пользователей загружать приложение и предполагаем, что большинство из них получит доступ к нему с мобильного сафари
  • Принять факт, что данные могут отличаться (это может быть не альтернативой вам в зависимости от характера вашего приложения)
  • Возьмите мой подход "конвертируйте" свое веб-приложение в родное приложение через встроенные функции Phonegap. Если да, взгляните на этот учебник Джонатана Старка.

Надеюсь, это помогло прояснить хотя бы части его.