2009-08-07 15 views
12

Voglio memorizzare in un NSMutableDictionary alcuni valori null utilizzando NSNull e quindi serializzare questi dati utilizzando un elenco di proprietà. Il problema è NSNull non consentito e viene visualizzato il messaggio di errore "L'elenco delle proprietà è in formato non valido". C'è una soluzione per questo? Sembra molto sorprendente che non abbiano inserito NSNull nell'elenco di oggetti Plist validi.Come serializzare un NSDictionary/NSArray/Property Property (plist) che contiene NSNull

+0

La risposta fornita da Saurabh Wadhwa funziona solo grande, ho solo usato io stesso, peccato il manifesto originale non è in giro per accettarlo ... –

risposta

5

No, non è possibile inserire NSNull in un elenco di proprietà. (Trivia: il formato dell'elenco delle proprietà binarie supporta effettivamente i valori null, ma lo scrittore non implementa il supporto.)

Per un dizionario, la soluzione più semplice consiste semplicemente nel filtrare i valori nulli, quindi {foo = "bar"; baz = null; } diventa {foo = "bar"; }.

+0

La sua non è esattamente la stessa cosa poiché ho bisogno dei valori nulli per indicare che la chiave esiste ma non ha valori corrispondenti (cioè so già che c'è una chiave senza dati in contrapposizione alla sua nuova chiave di cui non sono a conoscenza). –

+0

Forse potresti serializzare sia A) un dizionario con solo i tasti che hanno un valore corrispondente, e B) un array di tutte le chiavi conosciute, indipendentemente dal fatto che abbiano dati collegati. In definitiva, non è possibile inserire NSNull in un plist direttamente, quindi è necessario trovare una soluzione alternativa. –

3

Dalla documentazione di NSPropertyListSerializationClass:

Un oggetto elenco di proprietà. plist deve essere un tipo di oggetto NSData, NSString, NSNumber, NSDate, NSArray o NSDictionary . Gli oggetti contenitore devono anche contenere solo questi tipi di oggetti.

Quindi è necessario avere uno di quelli. A seconda del tipo di dati, è possibile inserire un segnaposto anziché NSNull e quindi eseguire un processo prima/dopo aver caricato il file .plist (ad esempio, utilizzando un oggetto NSData a lunghezza zero per rappresentare NSNull nel plist). Esattamente quale tipo di segnaposto dipenderebbe dal tipo di dati che stai memorizzando e dalla scelta di qualcosa da evitare. Quindi, dopo aver caricato, converte nuovamente NSData vuoto in NSNull.

+0

Seriamente cosa c'è di sbagliato con i programmatori di apple ??? Odio dover scrivere un codice del genere. –

+3

DD, se quello che vuoi è la serializzazione generale, usa NSCoder. Gli elenchi di proprietà hanno un set fisso di tipi, quindi non importa quanto sia espanso ci sarà sempre bisogno di convertire qualcosa. –

+1

Se non ti piacciono le restrizioni degli elenchi di proprietà (che non supportano NSNull, come indica la documentazione), allora non utilizzare gli elenchi di proprietà. Come suggerisce l'altro commentatore, usa il tuo formato di serializzazione. Supporto NSPropertyList! = Serializzazione. – AlBlue

9

Invece di utilizzare un elenco di proprietà, prendere in considerazione l'utilizzo di un NSKeyedArchiver e NSKeyedUnarchiver. Gli elenchi di proprietà hanno un set fisso di tipi e questo non include NSNull e non è pensato per essere esteso.

Ecco i collegamenti alla relativa documentazione: NSCoding, NSKeyedArchiver e NSKeyedUnarchiver.

14

Converto NSArray o NSDictionary in NSData prima della serializzazione. Di seguito è riportata una categoria su nsarray per serializzare e deserializzare. Questo comfortableby gestisce alcuni dati che vengono nsnull

@implementation NSArray(Plist) 

-(BOOL)writeToPlistFile:(NSString*)filename{ 
    NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self]; 
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString * documentsDirectory = [paths objectAtIndex:0]; 
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; 
    BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES]; 
    return didWriteSuccessfull; 
} 

+(NSArray*)readFromPlistFile:(NSString*)filename{ 
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString * documentsDirectory = [paths objectAtIndex:0]; 
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; 
    NSData * data = [NSData dataWithContentsOfFile:path]; 
    return [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
} 
+0

Molto buono! È incredibile questo funziona (che ho appena verificato) quando i metodi più comuni negli archiviatori con chiave non lo fanno. –

Problemi correlati