2009-03-15 7 views
10

J'ai un objet personnalisé qui hérite simplement de NSObject. Il a 3 membres - deux flotteurs et un NSDate.Objets personnalisés persistants

Mon application va avoir un tableau avec un certain nombre de ces objets qui défilent, et j'ai besoin de le conserver entre les exécutions. Comment puis-je accomplir cela?

J'ai pensé à utiliser un SQLite db, mais je pense que c'est un peu exagéré puisque la seule requête que je ferais serait select *.

Dans un monde idéal, je voudrais utiliser un fichier plist xml. Je ne suis pas sûr de pouvoir le faire avec mon objet personnalisé. Je sais qu'il existe un ensemble d'objets Liste de propriétés, et que NSArray relève de cela, mais writeToFile:atomically: fonctionne uniquement avec les objets de liste de propriétés.

Toutes les pensées seraient appréciées, merci!

Répondre

21

NSCoding fera exactement ce que vous voulez. Je vous recommande de lire à ce sujet dans les documents Apple, mais je pensais que c'était assez simple à utiliser. Votre classe (et toutes les classes enfants) devra implémenter le protocole NSCoding et vous devrez ajouter les méthodes -encodeWithCoder: et -initWithCoder: à vos objets. La plupart des classes de structure communes implémentent déjà NSCoding.

Le code pour votre classe ressemblera à quelque chose comme ceci:

-(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; 
} 

Il vous est recommandé d'ajouter un numéro de version lors de l'encodage pour vous donner la flexibilité pour gérer les changements à votre format d'archive dans les futures versions.

Dans ma classe, j'ai ajouté une méthode pratique pour archiver mon objet:

-(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]; 
} 

et un autre à désarchiver ou créer un nouvel objet:

+(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; 
} 

Étant donné que votre objet de niveau supérieur est un NSArray, vous devrez modifier les deux dernières méthodes pour votre cas, mais la plupart du code standard sera le même.

+0

Et cela produirait une belle plist? J'avais l'impression que l'écriture de NSData ne ferait que produire des données sérialisées et non pas une plist. – Jasarien

+0

Cela produit une archive NSCoding - un fichier avec des copies préservées de vos objets, un peu comme un fichier nib (mais vous ne pouvez pas utiliser Interface Builder pour l'éditer). Le "Guide de programmation des archives et des sérialisations pour Cocoa" dans votre documentation l'expliquera. –

+0

Par défaut, il archive dans un plist binaire, mais vous pouvez le changer en plist xml si vous le souhaitez. Malheureusement, il n'est pas vraiment lisible par l'homme car il contient des métadonnées de classe et de pointeur ainsi que vos données d'objet. –

0

Si vous voulez récupérer un sous-ensemble d'objets, SQLite est de loin votre meilleur choix.

Sinon, c'est un choix entre le format plist et le NSCoding. Plist vous demande de pouvoir convertir vos objets personnalisés en quelque chose qui convienne au plist, puis de convertir le plist dans vos objets, mais NSCoding est un peu plus difficile à enrouler et ne peut pas être facilement édité (ou examiné) à la main .

+0

Je n'utiliserai pas de sous-ensembles. J'ai juste besoin de la liste complète persisté. Comment pourrait-on convertir un objet pour qu'il soit respectueux des plistes? J'ai cru comprendre qu'il y avait un ensemble d'objets de liste de propriétés et c'est tout. Mon objet n'est pas fait de tout ce qui n'est pas plistable ... – Jasarien

Questions connexes