views:

109

answers:

1

I am trying to save an array of images to the documents folder. I managed to save an image as NSData and retrieve it using the method below, but saving an array seems to be beyond me. I've looked at several other questions that relate and it seems I'm doing everything right.

Adding the image as NSData and saving the image:

[imgsData addObject:[[NSData alloc] initWithData:UIImageJPEGRepresentation(img, 1.0)]];
[imgsData writeToFile:dataFilePath atomically:YES];

Retrieving the data:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"imgs.dat"];
[self setDataFilePath:path];

NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:dataFilePath]) 
 imgsData = [[NSMutableArray alloc] initWithContentsOfFile:dataFilePath];

So, writing an image as NSData using the above works, but not an array of images as NSData. It inits the array, but it has 0 objects, which isn't correct, since the array I am saving has several. Does anyone have any ideas?

+3  A: 

First of all, you should brush up Cocoa Memory Management, the first line of code is a little bit of a worry.

For data serialisation, you may like to have a go with NSPropertyListSerialization. This class serialises arrays, dictionaries, strings, dates, numbers and data objects. It has an error reporting system, unlike the initWithContentsOfFile: methods. The method names and arguments are a bit long to fit on one line, so sometimes you may see them written with Eastern Polish Christmas Tree notation. To save your imgsData object, you can use:

NSString *errString;
NSData *serialized =
    [NSPropertyListSerialization dataFromPropertyList:imgsData
                                               format:NSPropertyListBinaryFormat_v1_0
                                     errorDescription:&errString];

[serialized writeToFile:dataFilePath atomically:YES];

if (errString)
{
    NSLog(@"%@" errString);
    [errString release]; // exception to the rules
}

To read it back in, use

NSString *errString;
NSData *serialized = [NSData dataWithContentsOfFile:dataFilePath];

// we provide NULL for format because we really don't care what format it is.
// or, if you do, provide the address of an NSPropertyListFormat type.

imgsData =
    [NSPropertyListSerialization propertyListFromData:serialized
                                     mutabilityOption:NSPropertyListMutableContainers
                                               format:NULL
                                     errorDescription:&errString];

if (errString)
{
    NSLog(@"%@" errString);
    [errString release]; // exception to the rules
}

Check the contents of errString to determine what went wrong. Keep in mind that these two methods are being deprecated in favour of the dataWithPropertyList:format:options:error: and propertyListWithData:options:format:error: methods, but these were added in Mac OS X 10.6 (I'm not sure if they're available on iOS).

dreamlax
Good point regarding memory management. +1
Moshe
Wow, perfect! Thanks, it works wonders!
Ginamin
Also, on a side note, dataWithPropertyList:format:options:error: is avaiable in iOS 4. So not useful for me, but may help with any iPhone 4 programmers.
Ginamin