I’m using NSCoding to manage a custom object with a few different fields, one of them images. I’m only targeting iOS 5.0+ and have switched to ARC. I have everything working but am focused on performance–I haven’t seen a question like this asked, so here it goes:
I transform the UIImage into NSData and add it to the main NSCoding file (a plist, if it matters) for storage on the disk. If there is more than one image, the image names become sequential (e.g. image1, image2, image3.) I then use the image both in a UITableView (as a resized thumbnail) and in a detail view. The negative side to this is that the plist balloons in size, which means slow initial load times when I use it because it’s loading all of the NSData at once.
What is the best way to eliminate this problem and only force the loading of one image at a time?
What I’ve thought of:
I write the NSData to the disk, add an array to the plist, and add only a reference to the filename of each image to the array. I suppose I’d then reference the image filename at specified position, find it on the disk, and use it?
Any and all thoughts would be most welcome. I’m more stuck on the conceptual implementation than anything else and, funnily enough, this is not an oft-discussed topic.
Thanks,
EDIT:
As requested below, here’s an example of taking an image and turning it into NSData:
UIImage *originalImage;
NSData *imageData = UIImagePNGRepresentation(originalImage);
//I save it all to the app's document directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//I am using the images in a tableView and thus found it easiest to append the row number to each image filename.
//'y' below is just an integer that corresponds to the number of items in the master array
NSString *fileName = [NSString stringWithFormat:@"image%d.png",y];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:fileName];
[imageData writeToFile:documentsDirectory atomically:YES];
// NSLog(@"The filename is %@", fileName);
//newObject is an instance of my NSCoding object
[newObject setImageName: fileName];
Your suggestion is sound. Imagine a relational database. I would never save the images in one field as a blob. A filesystem is a very good place to save binary date in large amounts. It also gives you easy ways to duplicate files and so on.
So saving a reference in your plist will make parsing really fast and lazy loading an easy task to process images only when you need them.