Warum werden NSUserDefaults nicht nach leerem Akku IOS7 gelesen?

8

Ich verwende NSUserDefaults, um zu speichern, ob die App EULA und PP akzeptiert wurden (unter anderem). Das funktioniert im Allgemeinen gut. Ich kann anfangen, beenden, dann zurück zur App und es liest den Wert in Ordnung. Ich kann die App töten und neustarten - liest die Voreinstellungen gut. Ich kann das Telefon neu starten, dann starte die App neu und es liest die Standardeinstellungen.

Aber wenn das Telefon von einer leeren Batterie neu startet, öffne ich die App und werde aufgefordert, meine EULA wieder ein PP zu akzeptieren. Dies passiert nur auf meinem iPhone5 auf IOS7. Ich habe ein 3GS auf IOS6, das nicht das gleiche Verhalten zeigt.

Ich vermute, dass es sich um ein ähnliches Problem handeln könnte wie das Problem hier , aber dies bezieht sich auf Berechtigungsprobleme im Schlüsselbund. Würden die gleichen Berechtigungen für NSUserDefaults gelten?

Hat jemand ähnliche Probleme auf IOS7 mit NSUserDefaults erfahren?

    
muldercnc 09.12.2013, 07:03
quelle

2 Antworten

21

Nach dem Experimentieren und Googeln waren die Schlussfolgerungen, zu denen ich kam, wie folgt:

Die Signifikante Update-Änderung und tatsächlich jeder Prozess, der die App hinter dem Sperrbildschirm startet, ist hier das Problem. Die Datei .plist, die [NSUserDefaults defaultUser] lädt, ist geschützt (NSFileProtectionCompleteUntilFirstUserAuthentication), sodass sie erst nach dem ersten Entsperren nach dem Start der App zugänglich ist. Wenn also ein Prozess Ihre App im Hintergrund startet und Ihre App versucht, auf die Standardeinstellungen von defaultUser zuzugreifen, kann sie die Datei nicht laden und gibt Ihnen so einen neuen leeren Satz von Benutzervorgaben.

Was hier in meinem Fall passiert ist, dass die App dann in einen Zustand des Wartens auf die EULA und PP ging, da sie von den Vorgaben (die nicht gelesen werden konnten) gelesen hatte, dass sie noch nicht akzeptiert worden waren . Nach dem Entsperren des Telefons und dem erneuten Öffnen der App - die bitte beachten Sie bereits "gestartet" - gibt es einige Prozesse, die NSUserDefaults schreiben, einige in meiner App und einige in Bibliotheken meiner App verwendet. In den meisten Fällen, die ich anrief, synchronisierte ich die Standardeinstellungen und sprengte damit die alten Standardeinstellungen, die nicht gelesen werden konnten. Ich kann mir vorstellen, dass dies für viele Leute der Fall sein könnte.

Es gibt ein paar verschiedene Lösungen.

Zuerst schrieb ich eine NSUserDefaults entsprechende Klasse, die ein NSMutableDictionary einwickelte und das Wörterbuch in einer .plist im Library / Application Support speicherte. Ich habe den Schutz der Datei auf NSFileProtectionNone geändert. Beachten Sie, dass dies nicht ratsam ist, wenn Sie vertrauliche Informationen in dieser Datei speichern. Beachten Sie auch, dass Sie die Berechtigungen für die Datei bei jedem Schreiben festlegen müssen. Etwas wie:

%Vor%

Diese Methode funktioniert gut, aber wie sich herausstellt, hatte ich ein anderes Problem mit Daten, die ich vom Schlüsselbund gelesen und geschrieben habe. Siehe den Link in meiner Frage, es ist das gleiche Problem. Die Keychain-Werte haben den gleichen Schutz bis zum ersten Entsperren nach dem Start der App. Ich wollte den Schutz nicht aus dem Schlüsselbund entfernen, und ich war auch nicht wirklich damit zufrieden, den Schutz von meinen benutzerdefinierten Benutzereinstellungen zu entfernen.

Die nächste Lösung besteht also darin, das Problem tatsächlich zu lösen. Versuchen Sie nicht, auf geschützte Daten zuzugreifen, wenn die App hinter dem Sperrbildschirm gestartet wird! Das bedeutet, dass ich erkennen muss, dass die App hinter dem Sperrbildschirm gestartet wird, und dann warten, bis die App entsperrt ist, bevor ich meine Benutzerstandardwerte und Schlüsselbundwerte lese.

Die erste Anforderung besteht darin, den Anwendungsstart zu prüfen, ob geschützte Daten verfügbar sind, also vielleicht in applicationDidLaunch oder woanders geeignet.

%Vor%

Wenn dies beim Start der App nicht der Fall ist, befinden Sie sich hinter dem Sperrbildschirm. Sie sollten an dieser Stelle anhalten und von allen Vorgängen absehen, die auf NSUserDefaults oder Keychain (oder eine andere geschützte Datei!) Zugreifen. Sie müssen dann auf ein Signal warten, dass die geschützten Daten verfügbar sind. Das AppDelegate empfängt Folgendes, wenn der Benutzer den Sperrbildschirm entsperrt:

%Vor%

Sobald Sie erhalten haben, dass Sie die Ausführung Ihrer Anwendung fortsetzen können.

In meinem Fall kontrolliere ich alles in einer Singleton-Klasse. Wenn diese Klasse erstellt wird (was nur beim Start der App geschieht), überprüfe ich, ob geschützte Daten verfügbar sind oder nicht, und abonniere NSNotificationCenter für die gleiche Benachrichtigung:

%Vor%

Mit dieser zweiten Methode ist das Problem also gelöst und die Daten bleiben geschützt und alle sind glücklich.

    
muldercnc 02.01.2014 23:02
quelle
1

Dies ist immer noch das Verhalten auf IOS 9.0 GM.

    
Jacob Wallström 18.09.2015 09:23
quelle

Tags und Links