• Das kreative Thema des Monats Oktober wird vor allem diejenigen unter Euch besonders ansprechen, denen Do-it-yourself quasi im Blut liegt. Zeigt uns Eure Improvisationskünste oder fotografiert, was andere Leute sich so im Alltag zusammengestrickt haben. --> Zum Mitmachen bitte hier klicken

Preferenzen persistet speichern

MrSpock

Empire
Registriert
01.08.09
Beiträge
86
Hallo,

ich möchte gerne, dass ein paar Einstellungen unter /Library/Preferences und dann sagen wir de.abc.myProg gespeichert werden. Unter XCode habe ich den Bundle identifier auf da.abx-myProg gesetzt.

Mit dem Code:

Code:
    NSDictionary *defaultDict=
            [NSDictionary dictionaryWithObjectsAndKeys:
     @"wert1", @"key1",
     @"wert2", @"key2r",
     @"wert3", @"key3", nil];
    
    id defaults = [NSUserDefaults standardUserDefaults];
    
    [defaults registerDefaults:defaultDict];
    [defaults synchronize];
habe ich versucht, die 3 Einträge zu speichern, aber es wird keine Datei mit dem o.g. Namen erzeugt. Was mache ich falsch?

Ich nutze XCode 3.2.1 64 bit.
 
Hast mal die Dokumentation zu registerDefaults: gelesen? Setze die Werte direkt in den Usersefaults, ohne vorher ein extra Dictionary anzulegen.

MacApple
 
Hallo MacApple,

ja, ich habe die Dokumentation mehrfach gelesen, um genau zu verstehen, was die Nachricht auslöst, aber ich finde nicht warum mein Code nicht funktioniert.

Ich habe auch folgendes versucht:

[defaults registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
@"wert1", @"key1",
@"wert2", @"key2r",
@"wert3", @"key3", nil

Funktioniert aber auch nicht.

Ich habe es einmal so versucht:

[defaults setObject:@"wert1" forKey:@"key1"];
[defaults setObject:@"wert2" forKey:@"key2"];
[defaults setObject:@"wert3" forKey:@"key3"];

Das funktioniert. Aber der Sinn von registerDefaults ist ja gerade, ein Dictonary übernehmen zu können. Warum funktioniert es dann nicht?
 
ja, ich habe die Dokumentation mehrfach gelesen, um genau zu verstehen, was die Nachricht auslöst, aber ich finde nicht warum mein Code nicht funktioniert.
Dann sollte Dir aber folgendes aufgefallen sein:
Discussion
If there is no registration domain, one is created using the specified dictionary, and NSRegistrationDomain is added to the end of the search list.

The contents of the registration domain are not written to disk; you need to call this method each time your application starts. You can place a plist file in the application's Resources directory and call registerDefaults: with the contents that you read in from that file.
MacApple
 
Hallo MacApple,

das habe ich auch gelesen. Deshalb habe ich ja in meinem ersten Listing oben die synchronize Methode benutzt. Damit sollten die Werte im Speicher mit denen auf der Platte synchronisiert werden. Das funktioniert einwandfrei mit dem 2. Listing in #3 oben. Ich schicke die Nachricht standardUserDefault immer beim Starten der Application. Das Programm soll dann aus dem Pfad /Library/Preferencesdie Datei de.abx.myprog.plist lesen und im Speicher halten. Mit registerDefaults:defaultDict wollte ich, was immer gelesen wurde "ersetzen". Mit synchronize das Ergebnis wieder zurückschreiben. Wenn ich anstatt ein komplettes Dictonary mittels registerDefaults zu übergeben, die Werte einzeln mit setObject setze, dann funktioniert es. Wo ist bei der Idee mit registerDefaults mein Gedankenfehler?
 
das habe ich auch gelesen.
Warum wundert es Dich dann, dass die Werte, die Du mit registerDefaults: setzt, nicht auf der Festplatte landen?

Deshalb habe ich ja in meinem ersten Listing oben die synchronize Methode benutzt. Damit sollten die Werte im Speicher mit denen auf der Platte synchronisiert werden.
Aber nicht die, die du mit registerDefaults: setzt.

Mit registerDefaults:defaultDict wollte ich, was immer gelesen wurde "ersetzen". Mit synchronize das Ergebnis wieder zurückschreiben. Wenn ich anstatt ein komplettes Dictonary mittels registerDefaults zu übergeben, die Werte einzeln mit setObject setze, dann funktioniert es. Wo ist bei der Idee mit registerDefaults mein Gedankenfehler?
NSUserDefaults arbeitet mit verschiedenen Domains.

MacApple
 
Hallo MacApple,

ich habe auch den Teil des Manuals gelesen, aber offensichtlich nicht richtig verstanden. Ich habe es so verstanden, dass registerDefaults eine Liste von Domains von oben nach unten durchsucht und den ersten Treffer dann benutzt:

1. NSArgumentDomain , eine flüchtige Domain, die als Parameter beim Aufruf der Application mitübergeben werden muss
2. Application (Identified by the application’s identifier), eine persistente Domain, die in der ...Info.plist spezifiziert ist
3. ...

Ich übergebe keine Domain bei Aufruf (zumindest nicht bewustt), also hatte ich angenommen, dass der zweite Eintrag zum tragen kommt. In der plist Datei habe ich bundle identifier angegeben, so dass ich erwartet hätte, dass diese Domain benutzt wird.

Kann ich feststellen, welche Domain bei registerDefaults benutzt wird?
 
Kann ich feststellen, welche Domain bei registerDefaults benutzt wird?
Ja, ein Blick in die Dokumentation zu Methode registerDefaults: gibt Dir die Antwort:
Adds the contents the specified dictionary to the registration domain.
Und in dem von mir verlinkten „User Defaults Programming Topics for Cocoa“ steht auch:
You set NSRegistrationDomain defaults programmatically with the method registerDefaults:.
Mit registerDefaults: legst Du die Grundeinstellungen Deines Programms fest, die so lange gelten, bis der Anwender sie nach seinen Wünschen eingestellt hat.

MacApple
 
Hallo MacApple,

jetzt hab ich es hinbekommen und auch verstanden. :-)

Also wenn mein Programm zum allererstenmal gestartet wird, existieren noch keine Einstellungen. Mit registerDefaults schreibe ich die Einstellungen in die registration domain, die flüchtig ist, und ganz am Ende der Suchliste steht. Da noch keinen anderen Einträge existieren, wird diese Einstellung genommen und ich kann diese nutzen, um z.B. vor dem Öffnen eines Einstellungsfenster die Werte aus [NSUserDefaults standardUserDefaults] lesen. Wenn ich jetzt Werte mit setObject in das Directory schreibe und anschließend synchronize aufrufe, werden diese, sofern der bundle identifier gesetzt ist, in die entsprechende plist Datei geschrieben. Startet mein Programm erneut, findet die Message standardUserDefaults jetzt die in der Suchliste weiter oben stehenden Einträge unter /Library/Preferences und nutzt die weiter hinten in der registration domain stehenden Werte nicht mehr.

Puh, das war schwierig!

Danke für deine Hinweise.
 
Super! Danke fuer die Erklaerung. Wollte ich schon lange mal auf deutsch und in langsam erklaert bekommen haben. Hab mich nie getraut zu fragen, weil ich Angst hatte es wuerde wieder einer kommen mit "Steht im Manual!"

Noch eine Frage. Bei einem Objective-C Commandline Tool kann man ja ebenfalls mit solchen Praeferenzen arbeiten. Aber kann ich dazu dann auch eine Pref Datei anlegen lassen oder gibt es da nur den Weg ueber eine Datei die eben als .plist angelegt wurde und nicht in /Library/Preferences liegt?