views:

1468

answers:

2

Hello,

I have an NSMutableArray that holds objects of the type Person (NSString,NSString,int) I am looking for a easy way to save this array to disc and load it again later.

I read alot about serialization but I never have done that. Maybe it's not the easiest way for me after all.

+7  A: 

The first step is to make your Person class implement the NSCoding protocol. The basic strategy is to implement two methods to serialize and un-serialize each of the object's instance variables that you want to persist between 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;
}

To actually write the objects to disk, you could use NSArray's writeToFile: method, or use the NSKeyedUnarchiver class if you want to be more explicit about how it's done. In both cases you can also put your array into another data structure (a dictionary for example) if you want to include other items (such as a file format number) in your data file.

Marc Charbonneau
+3  A: 

Mr. Charbonneau has the right idea. An NSCoder abstracts the specific serialization of your object, and lets you worry only about what needs to be serialized/deserialized. In -encodeWithCoder:, you might want to

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

as not all coders support keyed archiving.

In -initWithCoder, you should be sending -initWithCoder: – not simply -init – to super prior to initializing your object:

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

Alternatively, since your object is basically a property list already, you can add something like -[Person plistRepresentation]:

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

Then, to serialize an array of Persons, you can yourself transform the persons into their plistRepresentation and then use -[NSArray writeToURL:atomically:]. (You can of course also employ the methods of NSProperyListSerialization directly.)

Jeremy W. Sherman