iOS 'Web App' a différent localStorage que Mobile Safari

J'ai une webapp pour iPad avec la balise META:

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

Lorsque j'ouvre l'application à partir de la page d'accueil (version compatible avec l'application Web) ou que je saisis l'adresse dans Mobile Safari, le contenu de localStorage est différent. J'ai confirmé que les adresses sont identiques en imprimant location.href.

Toutes les modifications apscopes à localStorage lors de l'utilisation de Mobile Safari sont répercutées dans la version compatible avec l'application Web, mais les modifications apscopes à la version compatible avec l'application Web ne sont pas répercutées dans la version Mobile Safari.

Les domaines sont identiques, localStorage doit être identique. Que se passe-t-il dans le monde? Cela peut-il être réparé?


Mise à jour – Solution : Suite à la suggestion n ° 2 de la réponse acceptée (forçant l'user à être en mode plein écran) j'ai ajouté ce bit de code:

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

Ainsi, si vous utilisez un browser qui prend en charge le mode autonome et que vous n'êtes pas en mode autonome, redirigez-vous vers une page (instructions.html) qui montre à l'user comment append l'application à l'écran d'accueil.

Merci à tous pour leur consortingbution!

Résumé:

Safari et les applications Web en plein écran (également compatibles avec les applications Web) ont des caches d'écriture en memory séparés des données localStorage. Chaque fois que l'application en plein écran devient active, elle recharge le localStorage à partir du disque (ce qui lui permet de voir les changements de Safari). Cependant, lorsque Safari devient actif, il ne recharge pas datatables localStorage à partir du disque, de sorte qu'il ne verra pas les modifications apscopes dans l'application en plein écran à less que vous ne supprimiez Safari et ne le redémarriez.

Explication complète:

Il y a seulement deux problèmes difficiles en informatique:

  1. invalidation de cache
  2. nommer les choses
  3. erreurs hors-un

Le comportement buggy dans localStorage est le résultat du problème # 1. Voici pourquoi:

Lorsque le moteur du browser iOS se charge, il lit datatables de localStorage à partir du disque et les met en memory cache. Ensuite, chaque fois que vous lisez des données (par exemple, getItem ), datatables sont lues dans la memory et non sur le disque; et lors de l'écriture (par exemple, setItem ), datatables sont écrites en memory, puis vidées (de manière asynchronous) sur le disque. Puisque localStorage est synchrone, cette implémentation est totalement raisonnable. Si elle était sur disque pour toutes les lectures et les écritures, votre javascript serait bloqué à chaque lecture / écriture pour effectuer des opérations d'E / S sur disque.

Le problème est qu'une application Web en plein écran (appelons-la FSWA) utilise une instance distincte du moteur de browser iOS, et bien qu'un FSWA partage le même location sur le disque pour datatables localStorage, il ne partage pas le cache en memory. des données localStorage avec Safari.

Lorsque vous ajoutez le fait que FSWA recharge complètement (ce qui signifie que datatables localStorage sont rechargées à partir du disque) chaque fois qu'elles deviennent l'application active, vous obtenez le comportement que vous voyez.

Voici les coulisses …

  1. l'user effectue une modification qui écrit des données dans localStorage dans Safari
  2. Safari écrit des données dans le cache localStorage en memory de Safari
  3. Safari vide datatables localStorage du cache vers le disque
  4. l'user quitte le safari et lance le FSWA
  5. FSWA charge et lit datatables localStorage du disque dans le cache en memory
  6. l'user voit datatables qui ont été modifiées (à l'étape 1) dans Safari
  7. l'user fait un changement dans le FSWA qui écrit des données dans localStorage
  8. FSWA écrit des données dans son cache localStorage (le cache de Safari n'est pas mis à jour)
  9. FSWA vide ses données de cache localStorage sur le disque
  10. l'user revient à Safari
  11. Safari était déjà en cours d'exécution et il ne recharge pas datatables localStorage à partir du disque
  12. Safari lit les anciennes données de son cache en memory existant
  13. l'user ne voit pas les modifications effectuées à l'étape 7

Pour le prouver, vous pouvez tuer Safari entre l'étape 4 et l'étape 10. Ensuite, lorsque vous relancerez Safari à l'étape 11, il rechargera le localStorage à partir du disque et vous verrez datatables écrites par le FSWA.

Dans iOS5, j'ai été en mesure d'avoir deux applications Web en plein écran sur le même domaine qui pouvaient voir localStorage de l'autre. Cela a surmonté la différence entre le plein écran et Safari.

Cependant, avec iOS6, je dois merge mes deux applications Web en plein écran en une seule application.

En supposant que vous sauvegardiez datatables de stockage local correctement et si je ne me trompe pas, ce que vous rencontrez est un problème assez commun parmi les développeurs d'applications Web. Les cookies, les sessions et le stockage local semblent être stockés différemment dans l '"application web" (lancée depuis l'écran d'accueil) vers celle des données sauvegardées via un safari mobile.

J'ai fait des tests plutôt approfondis dans le passé et il me semble qu'il n'y a pas de solution de rechange assez bonne . Juste pour vous donner un exemple où mes collègues et moi avons rencontré un problème similaire: dans une application web que nous avons développée récemment, l'user doit se connecter avant d'accéder à toutes ses fonctionnalités. Si quelqu'un se connecte via un safari mobile et passe ensuite à la version téléchargée de l'application, on s'attend à être connecté mais ce n'est pas toujours le cas. Il est généralement nécessaire de se reconnecter, en suggérant que les cookies peuvent être stockés dans différentes "banques de données", en fonction de l'endroit où vous choisissez de lancer l'application.

De plus, comme le dit Calvin, il n'y a pas que des banques de données différentes. Les applications lancées via l'écran d'accueil semblent s'ouvrir plus lentement, les applications d'écran d'accueil sont toujours rechargées lorsqu'elles sont lancées suggérant un support multitâche, etc. Ma conclusion: le programme lance des applications web téléchargées! = Safari less la barre d'adresse et ne devrait donc pas être traité comme tel .

Bien que ce soit une fonctionnalité intéressante d'Apple , les applications Web écran d'accueil ne fonctionnent pas comme prévu ou comme espéré (comme si elles avaient été ouvertes en safari). Dans votre cas, en supposant que vous stockez datatables LS correctement et avez essayé différentes problème particulier, je suggère l'une des alternatives suivantes:

  1. Utilisez une database mysql pour r / w de / à la place
  2. Forcer les users à download l'application avant de l'utiliser (comme dans cet exemple )
  3. Ne pas encourager les users à download l'application et supposer que la plupart d'entre eux y accéder à partir de safari mobile
  4. Acceptez le fait que datatables peuvent différer (cela peut ne pas être une alternative à vous selon la nature de votre application)
  5. Suivez mon approche, "convertissez" votre application web en une application native via les fonctionnalités embeddedes de Phonegap . Si oui, jetez un oeil à ce tutoriel par Jonathan Stark.

J'espère que cela a aidé à clarifier au less certaines parties de celui-ci.