2009-08-14 4 views
6

Ho il dizionario memorizzato in NSUserDefaults e ho bisogno di aggiungere/rimuovere elementi in questo dizionario.Modificare gli oggetti in NSUserDefaults senza creare e reimpostare le copie

Mi da fastidio che per fare questo devo creare una copia mutabile dell'intero dizionario, cambiare un elemento e sostituire l'intero dizionario con una nuova copia.

copy = [[defaults objectForKey:@"foo"] mutableCopy]; 
[copy setObject:… forKey:@"bar"]; 
[defaults setObject:copy forKey:@"foo"]; 

e coinvolge ancora più copia e ri-impostazione per gli oggetti più in profondità nella gerarchia.

C'è un modo migliore?

Ho provato a utilizzare [defaults setValue:… forKeyPath:@"foo.bar"] ma non sembra funzionare (l'oggetto non è modificabile).

risposta

5

Generalmente creo una classe personalizzata per contenere tutte le preferenze dell'applicazione. Quella classe in grado di caricare le copie mutevoli dei userDefaults una volta, quando si avvia il programma, e quindi gestire tutte le incrementale salva lungo il percorso:

MyPreferences.h

@interface MyPreferences 
{ 
    NSMutableDictionary allPrefs; 
} 
@property (readonly) NSMutableDictionary * allPrefs; 
- (void)load; 
- (void)save; 
@end 

MyPreferences.m

@implementation MyPreferences 
@synthesize allPrefs; 

- (id)init 
{ 
    if ((self = [super init]) == nil) { return nil; } 
    allPrefs = [[NSMutableDictionary alloc] initWithCapacity:0]; 
    return self; 
} 

- (void)dealloc 
{ 
    [allPrefs release]; 
    [super dealloc]; 
} 

- (void)load 
{ 
    // load all mutable copies here 
    [allPrefs setObject:[[defaults objectForKey:@"foo"] mutableCopy] 
       forKey:@"foo"]; 
    // ... 
} 

- (void)save 
{ 
    [defaults setObject:allPrefs forKey:@"app_preferences"]; 
} 

@end 

Creo un'istanza di questa classe nella mia applicazione delegata e quindi chiama [myPrefs load] all'avvio dell'applicazione. Le preferenze modificate mentre il programma è in esecuzione possono essere modificate attraverso myPrefs, e quindi salvato chiamando [myPrefs save] lo desideri:

MyPreferences * myPrefs = [myApplication myPrefs]; 
[myPrefs setObject:bar forKeyPath:@"allPrefs.foo.bar"]; 
[myPrefs save]; 

Come bonus aggiuntivo, è possibile strutturare la classe MyPreferences come più ti piace, portando i vantaggi della Programmazione OO all'intero insieme di preferenze. Ho mostrato il modo semplice qui, semplicemente usando un dizionario mutevole, ma puoi rendere ogni preferenza in una proprietà, e fare l'elaborazione pre/post per oggetti più complicati come NSColor, per esempio.