Domanda

Vorrei salvare un oggetto NSMutableDictionary in NSUserDefaults . Il tipo di chiave in NSMutableDictionary è NSString , il tipo di valore è NSArray , che contiene un elenco di oggetti che implementa NSCoding . Per documento, NSString e NSArray sono entrambi conformi a NSCoding .

Ricevo questo errore:

  

[NSUserDefaults setObject: forKey:]: tentativo di inserire un valore non di proprietà .... della classe NSCFDictionary.

È stato utile?

Soluzione

Ho scoperto un'alternativa, prima di salvare, ho codificato l'oggetto root (oggetto NSArray ) usando NSKeyedArchiver , che termina con NSData . Quindi utilizzare UserDefaults salvare il NSData .

Quando ho bisogno dei dati, leggo il NSData e utilizzo NSKeyedUnarchiver per convertire NSData nell'oggetto.

È un po 'ingombrante, perché devo convertirmi in / da NSData ogni volta, ma funziona e basta.

Ecco un esempio per richiesta:

Salva:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *arr = ... ; // set value
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[defaults setObject:data forKey:@"theKey"];
[defaults synchronize];

Carica:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"theKey"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

L'elemento nell'array implementa

@interface CommentItem : NSObject<NSCoding> {
    NSString *value;
}

Quindi, nell'implementazione di CommentItem , fornisce due metodi:

-(void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:value forKey:@"Value"];
}

-(id)initWithCoder:(NSCoder *)decoder
{
    self.value = [decoder decodeObjectForKey:@"Value"];
    return self;
}

Qualcuno ha una soluzione migliore?

Grazie a tutti.

Altri suggerimenti

Se si salva un oggetto nelle impostazioni predefinite dell'utente, tutti gli oggetti, ricorsivamente, fino in fondo, devono essere oggetti dell'elenco delle proprietà. Conformarsi a NSCoding non significa nulla qui-- NSUserDefaults non li codificherà automaticamente in NSData , devi farlo tu stesso. Se la tua " lista di oggetti che implementa NSCoding " indica oggetti che non sono oggetti dell'elenco proprietà, quindi dovrai fare qualcosa con loro prima di salvare i valori predefiniti dell'utente.

Cordiali saluti le classi dell'elenco delle proprietà sono NSDictionary , NSArray , NSString , NSDate , NSData e NSNumber . Puoi scrivere sottoclassi mutabili (come NSMutableDictionary ) alle preferenze dell'utente ma gli oggetti che leggi saranno sempre immutabili.

Tutte le tue chiavi nel dizionario NSString sono? Penso che debbano essere per salvare il dizionario in un elenco di proprietà.

Risposta più semplice:

NSDictionary è solo un plist object , se le chiavi sono NSStrings . Quindi, archivia la " Key " come NSString con stringWithFormat .


Soluzione:

NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];

Vantaggi:

  1. Aggiungerà Valore stringa .
  2. Aggiungerà Valore vuoto quando il valore della variabile è NULL .

Hai preso in considerazione l'idea di implementare il protocollo NSCoding ? Ciò ti consentirà di codificare e decodificare su iPhone con due semplici metodi implementati con NSCoding . Innanzitutto dovrai aggiungere il NSCoding alla tua classe.

Ecco un esempio:

Questo è nel file .h

@interface GameContent : NSObject <NSCoding>

Quindi dovrai implementare due metodi del protocollo NSCoding.

    - (id) initWithCoder: (NSCoder *)coder
    {
        if (self = [super init])
        {
               [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]];
        }
        return self;
    }

    - (void) encodeWithCoder: (NSCoder *)coder
    {
           [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
    }

Controlla la documentazione su NSCoder per ulteriori informazioni. È stato molto utile per i miei progetti in cui ho bisogno di salvare lo stato dell'applicazione su iPhone se l'applicazione è chiusa e ripristinarla allo stato quando è di nuovo accesa.

La chiave è aggiungere il protocollo all'interfaccia e quindi implementare i due metodi che fanno parte di NSCoding .

Spero che questo aiuti!

Non esiste una soluzione migliore. Un'altra opzione sarebbe quella di salvare l'oggetto codificato su disco, ma sta facendo la stessa cosa. Entrambi finiscono con NSData che viene decodificato quando lo si desidera indietro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top