2014-09-02 9 views
13

Non è stato possibile memorizzare un NSArray in NsUserDefaults. L'applicazione viene schiantato
in questa linea [savedData setObject:jsonValue forKey:@"JSONDATA"];L'app si arresta in modo anomalo durante l'archiviazione di NSArray in NSUserDefaults

Di seguito è riportato il mio codice. e devo citare il mio errore di registro di seguito

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:jsonValue forKey:@"JSONDATA"]; 
[savedData synchronize]; 

log di errore:

*** Terminating app due to uncaught exception '`NSInvalidArgumentException`', reason: '*** - 

[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object <CFBasicHash 0x8c62b10 [0x1d2aec8]>{type = immutable dict, count = 3, 
    entries => 
+0

Può essere controllato il contenuto del jsonValue? –

+0

Credo che questo è ciò che stai cercando: http://stackoverflow.com/questions/19720611/attempt-to-set-a-non-property-list-object-as-an-nsuserdefaults# 19720674 – grimdox

+0

Please NSLog il valore che si sta tentando di memorizzare. Tutto ciò che abbiamo è un messaggio di errore che è stato interrotto molto prima che le cose diventassero interessanti. – gnasher729

risposta

42

Sì, non possono essere salvati in questo modo in NSUserDefaults.

Sto scrivendo un codice qui sotto per favore dare un'occhiata e per ulteriori approfondimenti go look apple doc va bene.

Codice è qui:

// per il risparmio

NSData *dataSave = [NSKeyedArchiver archivedDataWithRootObject:yourArrayToBeSave]]; 
[[NSUserDefaults standardUserDefaults] setObject:dataSave forKey:@"array"]; 

[[NSUserDefaults standardUserDefaults] synchronize]; // this will save you UserDefaults 

// Per il recupero

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"]; 
NSArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
+0

Perché convertire NSData in un NSArray e tornare a NSData? – gnasher729

+0

@ gnasher729 si prega di fare riferimento alla domanda ... "yourArrayToBeSaved" è un oggetto non-elenco di proprietà che è il motivo per cui non può essere salvato in NSUserDefaults quindi la modifica di NSArray in NSData e ritorno –

+0

Sì, sto usando questo ma l'arresto anomalo dell'app. –

0

È necessario allocare prima NSArray allora si può passare i valori in ordine. Non puoi passare direttamente il valore.

NSArray * a = [[NSArray alloc] initWithObjects: [NSJSONSerialization JSONObjectWithData: opzioni dati: 0 errore: nil], nil];

+1

Non ha senso. L'inserimento di un oggetto JSON in un array non lo rende un oggetto di elenco di proprietà. – gnasher729

1

penso jsonValue è NSDictionary non NSArray ..

id jsonValue = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; 
    if ([jsonValue isKindOfClass:[NSDictionary class]]) 
    { 
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 
    [savedData synchronize]; 
    } 

// (OR)

NSDictionary *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 
[savedData synchronize]; 

Inoltre penso che non è possibile memorizzare la NSDictionary direttamente in NSUserDefaults..Go attraverso @kshitij godara per farlo fare/salvare ..

È possibile utilizzare NSKeyedArchiver per scrivere il tuo dizionario su un NSData.

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonvalue]; 
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"JSONDATA"]; 

Per i dati recupero:

NSData *dictionaryData = [defaults objectForKey:@"JSONDATA"]; 
NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:dictionaryData]; 

Spero che questo ti aiuta ..!

+1

Si inizia con NSData. Converti NSData in un dizionario o in un array. Converti il ​​dizionario o l'array in NSData e lo memorizzi. Riesci a vedere i due passaggi completamente inutili nel tuo codice? – gnasher729

3

Mentre la risposta di kshitij è corretta, purtroppo non finisce qui. Se si desidera salvare oggetti personalizzati all'interno di NSUserDefaults, l'oggetto personalizzato deve implementare il protocollo NSCoding e sovrascrivere i metodi initWithCoder e encodeWithCoder. Un esempio di tale può essere come:

@interface Book : NSObject <NSCoding> 
@property NSString *title; 
@property NSString *author; 
@property NSUInteger pageCount; 
@property NSSet *categories; 
@property (getter = isAvailable) BOOL available; 
@end 

@implementation Book 

#pragma mark - NSCoding 

    - (id)initWithCoder:(NSCoder *)decoder { 
     self = [super init]; 
     if (!self) { 
      return nil; 
     } 

     self.title = [decoder decodeObjectForKey:@"title"]; 
     self.author = [decoder decodeObjectForKey:@"author"]; 
     self.pageCount = [decoder decodeIntegerForKey:@"pageCount"]; 
     self.categories = [decoder decodeObjectForKey:@"categories"]; 
     self.available = [decoder decodeBoolForKey:@"available"]; 

     return self; 
    } 

    - (void)encodeWithCoder:(NSCoder *)encoder { 
     [encoder encodeObject:self.title forKey:@"title"]; 
     [encoder encodeObject:self.author forKey:@"author"]; 
     [encoder encodeInteger:self.pageCount forKey:@"pageCount"]; 
     [encoder encodeObject:self.categories forKey:@"categories"]; 
     [encoder encodeBool:[self isAvailable] forKey:@"available"]; 
    } 

@end 
1

provare come questo

NSMutableArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
    NSData *yourEncodedObject = [NSKeyedArchiver archivedDataWithRootObject: jsonValue]; 

     NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
     [userData setObject: yourEncodedObject forKey:@"JSONDATA"]; 
    [savedData synchronize]; 
+0

puoi mostrarti i dati JSON, cosa c'è in NSArray * jsonValue? – Sport

1

NSUserDefaults accetta elenco delle proprietà di oggetti - NSDictionary, NSArray, NSString, NSNumber, NSDate e NSData.I documenti JSON contengono NSDictionary, NSArray, NSString, NSNumber e NSNull. Viene visualizzata la differenza: gli oggetti dell'elenco delle proprietà non possono contenere valori NSNull.

Se l'oggetto JSON contiene un oggetto NSNull (il documento JSON che è stato analizzato conteneva un valore "null"), non è possibile memorizzarlo in NSUserDefaults. Oltre a ciò, tutti i commenti che dicono che non è possibile memorizzare i dati JSON in NSUserDefaults non hanno senso. Sono solo gli oggetti NSNull che causano un problema.

C'è una soluzione molto, molto semplice al tuo problema. Memorizza i dati JSON originali come oggetti NSData in NSUserDefaults. Quindi quando leggi NSUserDefaults, ottieni NSData e li analizzi. Invece di

NSArray *jsonValue =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:jsonValue forKey:@"JSONDATA"]; 
[savedData synchronize]; 

basta scrivere

NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults]; 
[savedData setObject:data forKey:@"JSONDATA"]; 
[savedData synchronize]; 
+0

Chiaramente la migliore risposta. –

0

NSUserDefaults deve essere utilizzato solo per un massimo di 500K dei dati (https://forums.developer.apple.com/message/50696#50696)

Se la memorizzazione di grandi quantità di applicazioni potrebbe bloccarsi, per esperienza personale ho' ho visto app che memorizzano 1 MB di dati in crash a/poco dopo [NSUserDefaults setObject:] e [NSUserDefaults synchronize];

Per verificare la quantità di dati utilizzati da un'app live, apri Xcode -> Finestra -> Dispositivi, seleziona il tuo dispositivo, seleziona la tua app in App installate e scarica il contenitore app. Predefiniti sono memorizzati in AppData-> Preferenze> your.app.plist

Un'alternativa al salvataggio dei dati per i valori di default degli utenti è quello di scrivere in un file:

-(void)saveObject:(NSObject *)object toFile:(NSString *)name { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name]; 
    [NSKeyedArchiver archiveRootObject:object toFile:appFile]; 
} 

-(NSObject *)loadFromFile:(NSString *)name { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:name]; 

    if([[NSFileManager defaultManager] fileExistsAtPath:appFile]) 
     return [NSKeyedUnarchiver unarchiveObjectWithFile:appFile]; 
    else{ 
     NSLog(@"No File: %@", name) ; 
     return nil ; 
    } 

}