2012-11-10 6 views
5

Sto scrivendo un'applicazione Cookbook e non sono stato in grado di trovare nulla su come salvare i dati di una classe che ho creato (la classe Recipe). L'unico modo che ho visto potrebbe essere quella di conservare possibilmente il contenuto di questa classe nel suo insieme senza salvare singolarmente ogni elemento della classe per ogni oggetto, rendendo questo metodo per la mia classe Ricetta:Come posso salvare un oggetto Objective-C che non è un oggetto elenco di proprietà o esiste un modo migliore per farlo rispetto a un elenco di proprietà?

-(void) writeToFile:(NSString *)file atomically:(BOOL)atomic{ 

} 

Ma ho assolutamente nessuna idea di come andrei a implementare questo per salvare questo oggetto su un file usando questo metodo. Alcune delle proprietà sono:

NSString* name; 
UIImage* recipePicture; 
NSDate* dateAdded; 
NSMutableArray* ingredients; //The contents are all NSStrings. 

Qualcuno sa come fare per salvare un oggetto della classe ricetta? Mi ha fatto impazzire non riuscire a capirlo. Qualsiasi aiuto sarebbe molto apprezzato. Ho già un .plist intitolato "RecipeData.plist". Avrei solo bisogno di scrivere ogni proprietà nel plist e inizializzare un nuovo oggetto di ricetta con quelle proprietà in fase di esecuzione?

risposta

5

Adottare:

@interface Recipe : NSObject<NSCoding> 

Implementare:

- (void)encodeWithCoder:(NSCoder *)coder 
{ 
    [coder encodeObject:name_ forKey:@"name"]; 
    [coder encodeObject:recipePicture_ forKey:@"recipePicture"]; 
    [coder encodeObject:dateAdded_ forKey:@"dateAdded"]; 
    [coder encodeObject:ingredients_ forKey:@"ingredients"]; 

}

// Decode an object from an archive 
- (id)initWithCoder:(NSCoder *)coder 
{ 
    self = [super init]; 
    if (self!=NULL) 
    { 
     name_ = [coder decodeObjectForKey:@"name"]; 
     recipePicture_ = [coder decodeObjectForKey:@"recipePicture"]; 
     dateAdded_ = [coder decodeObjectForKey:@"dateAdded"]; 
     ingredients_ = [coder decodeObjectForKey:@"ingredients"]; 
    } 
    return self; 
} 

Ora nel tuo salvare:

- (void) save:(NSString*)path recipe:(Recipe*)recipe 
{ 
    NSMutableData* data=[[NSMutableData alloc] init]; 
    if (data) 
    { 
     NSKeyedArchiver* archiver=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
     if (archiver) 
     { 
      [archiver encodeInt:1 forKey:@"Version"]; 
      [archiver encodeObject:recipe forKey:@"Recipe"]; 
      [archiver finishEncoding]; 

      [data writeToFile:path atomically:YES]; 

     } 
    } 
} 

E nel carico:

- (Recipe*) load:(NSString*)path 
{ 
    Recipe* ret=NULL; 
    NSData* data=[NSData dataWithContentsOfFile:path]; 
    if (data) 
    { 
     NSKeyedUnarchiver* unarchiver=[[NSKeyedUnarchiver alloc] initForReadingWithData:data]; 
     if (unarchiver) 
     { 
      int version=[unarchiver decodeIntForKey:@"Version"]; 
      if (version==1) 
      { 
       ret=(Recipe*)[unarchiver decodeObjectForKey:@"Recipe"]; 
      } 
      [unarchiver finishDecoding]; 
     } 
    } 
    return ret; 
} 
+0

È necessario aggiornare questo con gli altri due terzi della risposta: come codificarlo in un oggetto NSData per la memorizzazione in un elenco di proprietà e come decodificare i dati dall'elenco delle proprietà. – rmaddy

+0

Come ho detto nel commento qui sotto, grazie mille per avermi dedicato del tempo per mostrarmi come farlo. È stato davvero di grande aiuto. – crarho

+0

Dovresti chiamare 'self = [super initWithCoder: coder];' invece di 'self = [super init];'. Altrimenti, la tua superclasse non avrà i suoi dati codificati. –

2

Una possibilità (oltre codifica/decodifica) è quello di memorizzare ogni attributo della classe in un dizionario. Quindi scrivi il dizionario nel file. Il trucco consiste nel garantire che ogni oggetto inserito nel dizionario sia ammesso in un plist. Delle quattro proprietà che mostri, tutto tranne UIImage può essere memorizzato così com'è.

-(BOOL)writeToFile:(NSString *)file atomically:(BOOL)atomic{ 
    NSMutableDictionary *data = [NSMutableDictionary dictionary]; 

    [data setObject:name forKey:@"name"]; 
    [data setObject:dateAdded [email protected]"dataAdded"]; 

    NSDate *imageData = UIImagePNGRepresentation(recipePicture); 
    [data setObject:imageData forKey:@"recipePicture"]; 

    // add the rest 

    return [data writeToFile:file atomically:YES]; 
} 

L'ho aggiornato per restituire un BOOL. Se fallisce, significa che una delle due cose:

  1. Il file era inappropriato
  2. Si è tentato di salvare un oggetto adatto non plist nel dictonary

è necessario aggiungere codice per evitare cercando di aggiungere oggetti nil se ne hai. L'importante è assicurarsi che tutte le chiavi siano stringhe e che vengano memorizzati solo oggetti plist-friendly (NSString, NSNumber, NSDate, NSValue, NSData, NSArray e NSDictionary).

+0

Grazie mille per tutto l'aiuto. È molto apprezzato: questo problema mi ha infastidito da un po 'di tempo. – crarho