0

I have a database object and some photos objects.

The database object contains an integer property and a mutable dictionary property.

The integer keeps track of the next free number to use as a mutable dictionary key when I create a new photo object and the mutable dictionary contains pointers to photo objects.

Photo objects contain an image, an image description and the date the image was taken.

I've been using NSKeyedUnarchiver and NSKeyedArchiver to read and write these objects in and out when my applicationDidBecomeActive and applicationWillResignActive methods trigger.

And, it's all been working well. When applicationWillResignActive triggers, it calls NSKeyedArchiver and points it to the database object as the root. The coder then writes out the integer and then when it encounters the mutable dictionary, it descends into it and each photo object is called to save its properties which are the image, the description and the date.

As I said, it's all been working well. But, it has seemed slower and slower as the number of photos has increased so I did some timings.

I found that reading the archive in is roughly 25 times faster than writing it out.

So, I conceived the idea of only writing out the photos which are new or changed as a method of speeding up the write side. After all, most of the photos are from past sessions and I might have 30 or 50 of them from before and I might only shoot two or three new ones this time.

I created some flags that indicate if a photo is new or old. When applicationWillResignActive triggers and I find myself down in the photos object handling each encodeWithCoder call, I save the image, description and date if the photo is new and I skip saving if it is old.

Well, I did not get the result I'd hoped for :-)

When applicationWillResignActive triggers, all the photos I skip writing out end up getting written out as empty photo objects which overwrites the previous photo objects out there with the same key. Then, when I load them back in, I've got bupkis, nada, zip.

First question, I guess, is can I write out only part of my object tree and have the parts I don't write out still remain out there intact from an earlier full write? I'm beginning to wonder if that might be a naive idea.

Gallymon

Gallymon
  • 1,557
  • 1
  • 11
  • 21

2 Answers2

0

why don't you save the image only on the init method ? if you create the object chances are you want to save it. so place the flag hasChanges == off in the init method and you check that flag for saving...

stabilocode
  • 168
  • 8
0

Using archives of some array of objects is going to be increasingly inefficient as the archive grows. This is exacerbated by the fact that your objects include images. Two thoughts:

  1. You should consider using Core Data for storing this data. (You could use SQLite, directly, too, but Core Data is the preferred object persistence technology in iOS.) This way, when you want to save a new object, you just add that new object, and don't archive the whole collection of objects every time.

  2. Furthermore, if speed is of primary interest and if your images are large, SQLite (the database that Core Data employs by default) is inefficient when handling large BLOBs (i.e. things like images). So, as inelegant as it sounds, you probably want to save images to your Documents folder, and only store a image file URL or path in CoreData.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Rob, if I pull the images from the objects I am saving and restoring with NSKeyedArchiver to save into the documents folder, then I suspect that the remaining stuff will be plenty fast. So, what would be the advantage of adopting Core Data then other than positioning myself for a future with bigger data? – Gallymon Aug 18 '13 at 07:29
  • In the "Archives and Serializations Programming Guide" document, I saw the following: "Don’t read keys you don’t need. You aren’t required to read all the information from the archive for a particular object, ... , and it is much cheaper not to. However, unread data still contributes to the size of an archive, ...." Does this implies that if I have objects that I am writing out and I skip writing some of them, that the previous versions of those objects written earlier should still be there when I want to read all my objects in later. Or is it a misconception on my part? – Gallymon Aug 18 '13 at 07:37
  • @Gallymon In response to your first question, if you pulled images out of the objects, then the archiver should be fast enough, but it's still not a very efficient approach (why write all of the objects in the collection when you only have one new one). The logical tool is Core Data, but, sure, you can do whatever you want. – Rob Aug 18 '13 at 12:07
  • @Gallymon In response to your second question, no, that is not a logical inference of that statement from the guide. They're saying you should write everything, but you could, theoretically, only read portions. So you can speed up the reading process by not reading everything (which seems like a curious optimization that would be useful in rare situations). But that doesn't change the writing process. If you only want to write the new records, an archive is not the right tool. – Rob Aug 18 '13 at 12:10
  • Rob, I've had a good read through the Core Data stuff and I think you are right. It's the right solution for me on this project and it will be the right technology to have in hand going forward. Thanks. – Gallymon Aug 19 '13 at 07:11