In meiner App möchte ich Benutzereinstellungen in einer PLIST-Datei für jeden Benutzer anmelden, ich schreibe one class called CCUserSettings
, die fast die gleiche Schnittstelle wie NSUserDefaults
hat und liest und schreibt eine PLIST-Datei im Zusammenhang mit der aktuellen Benutzer-ID. Es funktioniert, hat aber eine schlechte Leistung. Jedes Mal, wenn der Benutzer [[CCUserSettings sharedUserSettings] synchronize]
anruft, schreibe ich eine NSMutableDictionary
(die die Benutzereinstellungen behalten) in eine PLIST-Datei, der folgende Code zeigt synchronize
von CCUserSettings
unter Auslassung einiger trivialer Details.Wie läuft `NSUserDefaults 'so schnell?
- (BOOL)synchronize {
BOOL r = [_settings writeToFile:_filePath atomically:YES];
return r;
}
Ich nehme an NSUserDefaults
in Dateien schreiben soll, wenn wir [[NSUserDefaults standardUserDefaults] synchronize]
nennen, aber es läuft wirklich schnell, ich schreibe ein demo zu testen, ist der Schlüssel Teil ist unten, laufen 1000 mal [[NSUserDefaults standardUserDefaults] synchronize]
und [[CCUserSettings sharedUserSettings] synchronize]
auf meinem iPhone6, das Ergebnis ist 0,45 Sekunden gegenüber 9,16 Sekunden.
NSDate *begin = [NSDate date];
for (NSInteger i = 0; i < 1000; ++i) {
[[NSUserDefaults standardUserDefaults] setBool:(i%2==1) forKey:@"key"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSDate *end = [NSDate date];
NSLog(@"synchronize seconds:%f", [end timeIntervalSinceDate:begin]);
[[CCUserSettings sharedUserSettings] loadUserSettingsWithUserId:@"1000"];
NSDate *begin = [NSDate date];
for (NSInteger i = 0; i < 1000; ++i) {
[[CCUserSettings sharedUserSettings] setBool:(i%2==1) forKey:@"_boolKey"];
[[CCUserSettings sharedUserSettings] synchronize];
}
NSDate *end = [NSDate date];
NSLog(@"CCUserSettings modified synchronize seconds:%f", [end timeIntervalSinceDate:begin]);
Wie das Ergebnis zeigt, NSUserDefaults
ist fast 20 mal schneller als mein CCUserSettings
. Jetzt beginne ich mich zu wundern, dass "NSUserDefaults wirklich jedes Mal in die PLIST-Dateien schreibt, wenn wir synchronize
aufrufen?", Aber wenn nicht, wie kann es garantieren, dass die Daten zurück in die Datei geschrieben werden, bevor der Prozess beendet wird (wie es der Prozess erlaubt) jederzeit getötet werden)?
In diesen Tagen habe ich eine Idee, um meine CCUserSettings
zu verbessern, es ist mmap
Memory-mapped I/O. Ich kann einen virtuellen Speicher zu einer Datei zuordnen und jedes Mal, wenn der Benutzer synchronize
aufruft, erstelle ich eine NSData
Methode mit NSPropertyListSerialization dataWithPropertyList:format:options:error:
und kopiere die Daten in diesen Speicher, das Betriebssystem schreibt den Speicher zurück in die Datei, wenn der Prozess beendet wird. Aber ich kann nicht eine gute Leistung erhalten, weil die Dateigröße nicht festgelegt ist, jedes Mal, wenn die Länge der Daten zunimmt, muss ich mmap
einen virtuellen Speicher, ich glaube, die Operation ist zeitaufwendig.
Entschuldigung für meine überflüssigen Details, ich will nur wissen, wie NSUserDefaults
arbeitet, um so gute Leistung zu erzielen, oder kann jemand gute Ratschläge haben, um meine CCUserSettings
zu verbessern?
Hier ist ein schöner Artikel über 'NSUserDefaults': http://dscoder.com /defaults.html. Sein Autor ist ein Ingenieur bei Apple, also ist es ziemlich sicher anzunehmen, dass er weiß, wovon er spricht :) – Losiowaty
@Losiowaty Danke für deinen Link, aber ich denke, es spricht über die Implementierung in MacOx, denn es heißt "Einen Wert setzen wird (schließlich ist es asynchron und tritt einige Zeit später in einem anderen Prozess auf) schreibe das gesamte plist auf die Festplatte, egal wie klein die Änderung war. Wenn Sie NSUserDefaults ändern und Ihre App ohne "synchronize" beenden, werden die Einstellungen nicht in die Datei geschrieben, daher glaube ich nicht, dass es einen anderen Prozess gibt, der die Datei in iOS schreibt. – KudoCC
Wenn Sie NSUserDefaults ändern und die App beenden, müssen Sie * sehr * schnell auf der Kill-Schaltfläche sein, um Daten zu verlieren. Ein paar Millisekunden oder so. Dies hat sich in iOS 8 geändert; vorher war es viel einfacher, Daten auf diese Weise zu verlieren. –