2009-05-04 17 views
7

Ho un NSMutableArray che contiene oggetti del tipo Persona (NSString, NSString, int) Sto cercando un modo semplice per salvare questo array sul disco e caricarlo di nuovo in seguito.Salva NSMutableArray su disco

Ho letto molto sulla serializzazione ma non l'ho mai fatto. Forse non è il modo più semplice per me, dopo tutto.

risposta

10

Il primo passo è rendere la classe Person implementare il protocollo NSCoding. La strategia di base consiste nell'implementare due metodi per serializzare e non serializzare ciascuna delle variabili di istanza dell'oggetto che si desidera mantenere tra le sessioni.

#pragma mark NSCoding Protocol 

- (void)encodeWithCoder:(NSCoder *)encoder; 
{ 
    [encoder encodeObject:[self foo] forKey:@"foo"]; 
    [encoder encodeDouble:[self bar] forKey:@"bar"]; 
} 

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

    [self setFoo:[decoder decodeObjectForKey:@"foo"]]; 
    [self setBar:[decoder decodeDoubleForKey:@"bar"]]; 

    return self; 
} 

Per scrivere in realtà gli oggetti su disco, è possibile utilizzare il metodo di NSArray writeToFile:, o utilizzare la classe NSKeyedUnarchiver se si vuole essere più espliciti su come è fatto. In entrambi i casi è anche possibile inserire la matrice in un'altra struttura di dati (ad esempio un dizionario) se si desidera includere altri elementi (come un numero di formato del file) nel file di dati.

+0

rimuovere quelli; 's –

+1

in realtà credo che non è necessario, sembra solo strano hah –

4

Il signor Charbonneau ha l'idea giusta. Un NSCoder astrae la serializzazione specifica del tuo oggetto e ti lascia preoccupare solo di ciò che deve essere serializzato/deserializzato. In -encodeWithCoder:, si potrebbe desiderare di

NSAssert1([encoder allowsKeyedCoding], 
      @"%@ does not support sequential archiving.", 
      [self className]); 

come non tutti i programmatori supportano l'archiviazione con chiave.

In -initWithCoder, si dovrebbe trasmettere -initWithCoder: - non semplicemente -init - a super prima di inizializzare l'oggetto:

self = [super initWithCoder:decoder]; 
if (!self) return nil; 
// now use the coder to initialize your state 

In alternativa, dal momento che l'oggetto è fondamentalmente un elenco di proprietà già, è possibile aggiungere qualcosa di simile -[Person plistRepresentation] :

- (NSDictionary *)plistRepresentation 
{ 
    return [NSDictionary dictionaryWithObjectsAndKeys: 
      [self firstName], @"firstName", 
      [self lastName], @"lastName", 
      [NSNumber numberWithInteger:[self age]], @"age", nil]; 
} 

Poi, per serializzare una serie di Person s, lei stesso può trasformare le persone in loro plistRepresentation e quindi utilizzare -[NSArray writeToURL:atomically:]. (Ovviamente si può anche utilizzare i metodi di NSProperyListSerialization direttamente.)

1

non funzionerà qui nel mio codice utilizzando writeToFile: atomicamente:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *issueURLsPlist = [documentsDirectory stringByAppendingPathComponent:@"test.plist"]; 

MyClass * myObject = [[MyClass alloc] init]; 
NSMutableArray * array = [[NSMutableArray alloc] init]; 
[array addObject:myObject]; 
[array writeToFile:issueURLsPlist atomically:YES]; 

MyClass.h

#import <Foundation/Foundation.h> 


@interface MyClass : NSObject <NSCoding> 
{ 

} 

@property (nonatomic,copy) NSString * foo; 
@property (nonatomic)  double bar; 


@end 

MyClass. m

#import "MyClass.h" 


@implementation MyClass 

- (id)init { 
self = [super init]; 
if (self) { 
    self.foo = @"test"; 
    self.bar = 0.4f; 
} 
return self; 
} 

#pragma mark NSCoding Protocol 

- (void)encodeWithCoder:(NSCoder *)encoder; 
{ 
[encoder encodeObject:[self foo] forKey:@"foo"]; 
[encoder encodeDouble:[self bar] forKey:@"bar"]; 
} 

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

[self setFoo:[decoder decodeObjectForKey:@"foo"]]; 
[self setBar:[decoder decodeDoubleForKey:@"bar"]]; 

return self; 
} 

@synthesize foo; 
@synthesize bar; 
@end 

Quando sto utilizzando una matrice con NSStrings allora il metodo writeToFile: atomic alleato: sta funzionando bene.