2009-03-15 7 views
10

Ho un oggetto personalizzato che eredita semplicemente da NSObject. Ha 3 membri: due float e uno NSDate.Oggetti personalizzati persistenti

La mia app avrà una matrice con un certo numero di questi oggetti che girano intorno, e ho bisogno di mantenerlo tra le esecuzioni. Come posso realizzare questo?

Ho pensato di utilizzare un db SQLite, ma penso che sia un po 'eccessivo dato che l'unica query che farei sarebbe select *.

In un mondo ideale mi piacerebbe utilizzare un file plist xml. Non sono sicuro di poterlo fare con il mio oggetto personalizzato. So che c'è un set di oggetti List delle proprietà e che NSArray rientra in quello, ma writeToFile:atomically: funziona solo con gli oggetti elenco di proprietà.

Ogni pensiero sarebbe apprezzato, grazie!

risposta

21

NSCoding farà esattamente quello che desideri. Vi consiglio di leggere su di esso nei documenti Apple, ma ho pensato che fosse abbastanza semplice da usare. La classe (e le eventuali classi secondarie) dovranno implementare il protocollo NSCoding e sarà necessario aggiungere i metodi -encodeWithCoder: e -initWithCoder: ai propri oggetti. La maggior parte delle classi di framework comuni implementano già NSCoding.

Il codice per la classe sarà simile a questo:

-(void) encodeWithCoder: (NSCoder*) coder { 
    [coder encodeInteger: versionValue forKey: versionKey]; 
    [coder encodeObject: myStuff forKey: myStuffKey]; 
} 

-(id) initWithCoder: (NSCoder*) coder { 
    self = [super init]; 
    if (! self) return nil; 
    myStuff = [[coder decodeObjectForKey: myStuffKey] retain]; 
    return self; 
} 

Si consiglia di aggiungere un numero di versione durante la codifica di dare flessibilità per gestire le modifiche al formato di archivio in versioni future.

Nella mia classe, ho aggiunto un metodo comodo per archiviare il mio oggetto:

-(void) archiveToFile: (NSString*) path { 
    NSMutableData *data = [[NSMutableData alloc] init]; 
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data]; 
    [archiver encodeObject: self forKey: myArchiveKey]; 
    [archiver finishEncoding]; 
    [archiver release]; 
    [data writeToFile: path atomically: YES]; 
    [data release]; 
} 

e un altro per decomprimere o di creare un nuovo oggetto:

+(MyArchive*) newFromFile: (NSString*) path 
      orWithMyStuff: (MyStuff*) myStuff 
{ 
    NSData *data = [[NSData alloc] initWithContentsOfFile: path]; 
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data]; 
    MyArchive *myArchive = [unarchiver decodeObjectForKey: myArchiveKey]; 
    [unarchiver finishDecoding]; 

    if (myArchive) { 
    [myArchive retain]; 
    } else { 
    myArchive = [[MyArchive alloc] initWithStuff: myStuff; 
    } 
    [unarchiver release]; 
    [data release]; 
    return myArchive; 
} 

Dal momento che l'oggetto di livello superiore è un NSArray, dovrai modificare gli ultimi due metodi per il tuo caso, ma la maggior parte del codice boilerplate sarà lo stesso.

+0

E quello produrrebbe un bel plist? Avevo l'impressione che scrivere NSData producesse solo dati serializzati e non un plist. – Jasarien

+0

Questo produce un archivio NSCoding, un file con copie conservate degli oggetti, un po 'come un file pennino (ma non è possibile utilizzare Interface Builder per modificarlo). La "Guida alla programmazione di archivi e serializzazioni per il cacao" nella documentazione lo spiegherà. –

+0

Per impostazione predefinita archivia in un plist binario, ma è possibile modificarlo in un plist xml se lo si desidera. Sfortunatamente non è veramente leggibile perché contiene metadati di classe e puntatore e anche i dati dell'oggetto. –

0

Se si desidera recuperare un sottoinsieme degli oggetti, SQLite è di gran lunga la scelta migliore.

In caso contrario, è una scelta tra il formato plist e NSCoding. plist richiede di essere in grado di convertire i tuoi oggetti personalizzati in qualcosa di plist-friendly e poi riconvertire il plist nei tuoi oggetti, ma NSCoding è un po 'più difficile da avvolgere e non può essere facilmente modificato (o esaminato) a mano .

+0

Non userò i sottoinsiemi. Ho solo bisogno di mantenere la lista completa. Come si fa a convertire un oggetto in modo da essere plist friendly? Ho capito che esiste un set di oggetti della lista delle proprietà e basta. Il mio oggetto non è fatto di nulla che non sia plasmabile ... – Jasarien