2009-05-04 9 views
7

J'ai un NSMutableArray qui contient des objets de type Person (NSString, NSString, int) Je cherche un moyen facile de sauvegarder cette matrice sur un disque et de le charger à nouveau plus tard. Je lis beaucoup à propos de la sérialisation, mais je ne l'ai jamais fait. Peut-être que ce n'est pas la façon la plus facile pour moi après tout.Enregistrer NSMutableArray sur le disque

Répondre

10

La première étape consiste à implémenter le protocole NSCoding dans votre classe Person. La stratégie de base consiste à implémenter deux méthodes pour sérialiser et déstratifier chacune des variables d'instance de l'objet que vous souhaitez conserver entre les sessions.

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

Pour écrire réellement les objets sur le disque, vous pouvez utiliser la méthode writeToFile: de NSArray, ou utiliser la classe NSKeyedUnarchiver si vous voulez être plus explicite sur la façon dont il est fait. Dans les deux cas, vous pouvez également placer votre tableau dans une autre structure de données (un dictionnaire par exemple) si vous souhaitez inclure d'autres éléments (comme un numéro de format de fichier) dans votre fichier de données.

+0

Enlevez ceux; –

+1

en fait je suppose que ce n'est pas nécessaire, il semble juste bizarre hah –

4

M. Charbonneau a la bonne idée. Un NSCoder résume la sérialisation spécifique de votre objet et vous permet de vous préoccuper uniquement de ce qui doit être sérialisé/désérialisé. En -encodeWithCoder:, vous pouvez

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

que tous les codeurs l'archivage immédiat à clé.

En -initWithCoder, vous devez enverrez -initWithCoder: - pas seulement -init - à super avant d'initialiser votre objet:

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

Alternativement, étant donné que votre objet est essentiellement une liste de propriétés déjà, vous pouvez ajouter quelque chose comme -[Person plistRepresentation] :

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

Ensuite, sérialiser un tableau de Person s, vous pouvez vous transformer les personnes en plistRepresentation puis utilisez -[NSArray writeToURL:atomically:]. (Vous pouvez bien sûr utiliser aussi les méthodes de NSProperyListSerialization directement.)

1

Il ne fonctionnera pas ici dans mon code en utilisant writeToFile: atomiquement:

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. Lorsque j'utilise un tableau avec NSStrings, alors la méthode writeToFile: atomic allié: fonctionne bien.

Questions connexes