2017-05-21 1 views
3

Je sais que UserDefaults est simplement destiné à enregistrer les préférences, mais ces préférences sont persistantes - les valeurs enregistrées dans UserDefaults sont maintenues sur un nombre illimité de lancements d'applications et sont toujours disponibles pour être lues tant que l'application reste installée ... droite?Est-il possible que les valeurs UserDefaults.standard ne soient pas disponibles pour être lues?

Est-il possible que ces valeurs soient effacées ou ne soient pas correctement accessibles à tout moment? Après des années d'utilisation de UserDefaults et en fonction de la cohérence des valeurs qu'ils contiennent, j'ai vu deux fois dans une journée de travail que lorsque mon application a lancé et vérifié une valeur booléenne simple, la valeur n'était pas correcte.

if defaults.bool(forKey: "beenLaunched") { 

Ce code s'exécute chaque fois que l'application est lancée. Si la valeur est true, je ne fais rien de plus, mais si c'est faux, je mets quelques valeurs car c'est le tout premier lancement de l'application par l'utilisateur puis j'appelle defaults.set (true, forKey: "beenLaunched") et defaults.set (0, forKey: "eventsCompleted") et quelques autres valeurs. J'ai trouvé this thread on the Apple forums dans lequel Eskimo disait "Pour la méthode centrale NSUserDefaults, -objectForKey :, un résultat de zéro signifie que la valeur est indisponible, mais il n'y a aucun moyen de distinguer cette clé et cette valeur peut être ' t être récupéré car les valeurs par défaut de l'utilisateur sont hors ligne. " (Cela semble être en référence à un cas spécifique de background launching while a device is locked)

Je peux trouver un moyen plus sûr d'enregistrer des données simples comme une valeur Bool, un Int, ou une chaîne, mais en utilisant UserDefaults pour ces types de Les valeurs ont toujours été simples, directes et fiables. Quelqu'un peut-il intervenir sur le sujet et si j'avais tort de croire à la persistance de UserDefaults?

Merci!

+1

Avez-vous appelé 'NSUserDefaults :: synchronize()' après avoir défini les valeurs? – Brandon

+2

Vous avez utilisé le framework Cocoa depuis 17 ans et ce n'est * pas * comment ça marche. :-) Je n'ai pas pris la peine de lire ce fil mais non, ça ne sera jamais "hors ligne" (même pas sûr de ce que ça veut dire *). –

+2

@Brandon non, je n'appelle généralement pas de synchronisation, mais n'a jamais eu de problème – RanLearns

Répondre

3

UserDefaults n'est pas un "service"; ce n'est jamais disponible pour votre application. Le fichier qu'il écrit est un PLIST (et donc toutes les valeurs sont stockées selon la norme PLIST). Par exemple, tous les nombres (y compris les booléens) sont stockés en tant que NSNumber dans le fichier et peuvent être récupérés par object(forKey:) ou bool(forKey:). Si vous utilisez la méthode object et que rien n'est défini pour cette valeur, vous obtenez nil, dont la valeur booléenne est false (ou 0). Même si vous utilisez la méthode booléenne (vous obtenez false). Cela signifie que peu importe la façon dont vous allez, vous obtiendrez toujours faux s'il n'y a pas de valeur ou une valeur de false. Concevez votre logique autour de cela (que vous avez déjà - "beenLaunched" sera vide et donc false s'il n'a jamais été lancé) et vous devriez aller bien. En ce qui concerne la suggestion de synchronize(), ignorez-le. À moins que vous ne fassiez quelque chose de vraiment bizarre avec les threads et l'accès aux préférences ou que vous ayez interrompu l'application immédiatement après avoir défini une valeur/un objet pour la clé du problème, cela n'a rien à voir avec cela. Par le tout premier paragraphe des documents, synchronize() est appelé périodiquement selon les besoins. En pratique, il est appelé à peu près immédiatement après un changement.

Pour le contexte, aucune de mes applications n'a jamais appelé synchronize() et certains d'entre eux sont assez vieux pour conduire. Jamais un seul problème. Si vous n'avez pas une très bonne justification pour appeler synchronize() vous-même vous n'avez presque certainement pas besoin et tente d'expliquer pourquoi vous avez besoin de saupoudrer partout ... sont souvent amusants.

Dans votre cas spécifique, la valeur bloquée après la première exécution plusieurs fois puis soudainement pas une fois. Est-il possible que vous ayez changé l'identifiant ou le nom de l'ensemble de votre application?Les valeurs par défaut sont stockées par identificateur + nom afin qu'une modification puisse effectivement "réinitialiser" les valeurs par défaut de votre application. Avez-vous exécuté votre application dans le simulateur et avez-vous simplement réinitialisé le contenu et les paramètres dans le simulateur? Sur votre appareil et supprimé l'application avant de la relancer sur l'appareil?

+0

Merci @JoshuaNozzi pour votre explication et la sauvegarde qu'il n'y a pas besoin d'appels manuels pour synchroniser() mais je suis sûr qu'ils ne feraient pas de mal. Je n'ai pas changé l'identifiant/nom, mais c'est bon à signaler. Je testais l'application en succession rapide sur des simulateurs avec différentes peaux d'appareils ainsi que sur des appareils réels. Je suis troublé par ne pas savoir ce qui a causé cela mais je ne peux pas reproduire le problème (même si cela s'est produit deux fois) et je ne veux pas douter de ce que je sais a toujours été une méthode fiable pour enregistrer dans un fichier PLIST. – RanLearns

+0

Depuis que Swift a introduit bool (forKey :), integer (forKey :), et string (forKey :) j'ai essayé d'utiliser ceux spécifiquement par opposition à object (forKey :) quand le type de variable est clairement connu – RanLearns

-1

Si vous travaillez dans swift, renvoyer nil signifie que objectforkey n'a reçu aucune valeur. Dans les autres cas, il renvoie toujours la valeur correcte si vous avez casté la valeur enregistrée correctement. Userdefaults est toujours disponible à utiliser, il ne peut jamais se déconnecter.