views:

524

answers:

2

Initially I thought this was going to work, but now I understand it won't because artistCollection is an NSMutableArray of "Artist" objects.

@interface Artist : NSObject {
    NSString *firName;
    NSString *surName;
}

My question is what is the best way of recording to disk my NSMutableArray of "Artist" objects so that I can load them the next time I run my application?

artistCollection = [[NSMutableArray alloc] init];

newArtist = [[Artist alloc] init];
[newArtist setFirName:objFirName];
[newArtist setSurName:objSurName];
[artistCollection addObject:newArtist];

NSLog(@"(*) - Save All");
[artistCollection writeToFile:@"/Users/Fgx/Desktop/stuff.txt" atomically:YES];

EDIT

Many thanks, just one final thing I am curious about. If "Artist" contained an extra instance variable of NSMutableArray (softwareOwned) of further objects (Applications) how would I expand the encoding to cover this? Would I add NSCoding to the "Applications" object, then encode that before encoding "Artist" or is there a way to specify this in "Artist"?

@interface Artist : NSObject {
    NSString *firName;
    NSString *surName;
    NSMutableArray *softwareOwned;
}

@interface Application : NSObject {
    NSString *appName;
    NSString *appVersion;
}

many thanks

gary

+7  A: 

Take a look at NSKeyedArchiver. Briefly :

NSData* artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection];
[artistData writeToFile: @"/Users/Fgx/Desktop/stuff" atomically:YES];

You'll need to implement encodeWithCoder: on your Artist class - see Apple's docs

Unarchiving (see NSKeyedUnarchiver) is left as an exercise for the reader :)

jdelStrother
+7  A: 

writeToFile:atomically: in Cocoa's collection classes only works for property lists, i.e. only for collections that contain standard objects like NSString, NSNumber, other collections, etc.

To elaborate on jdelStrother's answer, you can archive collections using NSKeyedArchiver if all objects the collection contains can archive themselves. To implement this for your custom class, make it conform to the NSCoding protocol:

@interface Artist : NSObject <NSCoding> {
    NSString *firName;
    NSString *surName;
}

@end


@implementation Artist

static NSString *FirstNameArchiveKey = @"firstName";
static NSString *LastNameArchiveKey = @"lastName";

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if (self != nil) {
        firName = [[decoder decodeObjectForKey:FirstNameArchiveKey] retain];
        surName = [[decoder decodeObjectForKey:LastNameArchiveKey] retain];
    }
    return self;
}   

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:firName forKey:FirstNameArchiveKey];
    [encoder encodeObject:surName forKey:LastNameArchiveKey];
}

@end

With this, you can encode the collection:

NSData* artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection];
[artistData writeToFile: @"/Users/Fgx/Desktop/stuff" atomically:YES];
Ole Begemann