1

I have an entity called "Person" and a set of UIImages for it (One-To-Many). When the user enters the images, he's asked to do so in a chronological order to the person's life.

When I save & restore the data from Core Data, I need to keep the images order.

How would you suggest me to do it?

10x

Rizon
  • 1,516
  • 4
  • 25
  • 45

2 Answers2

1

Add and maintain a sortOrder attribute on your image entity. Add a sort descriptor for this attribute to keep images sorted by it. Core Data doesn't support ordered collections for performance reasons.

Joshua Nozzi
  • 60,946
  • 14
  • 140
  • 135
  • 1
    +1 to Paul for noticing the date part - I didn't. If you already have it in your model, use it instead of a separate sort attribute. – Joshua Nozzi Dec 09 '10 at 18:38
  • +1 for simply adding a sort order attribute. You'll have to update the sort order on every item ordered after an insert or delete, but that shouldn't be too painful. – Matthew Frederick Dec 09 '10 at 19:11
  • Yep. Usually not painful. :-) – Joshua Nozzi Dec 09 '10 at 19:22
  • It would be great if Apple provided some way to treat a relationship as an ordered collection by specifying the order attribute in the MOM. – Joshua Nozzi Dec 09 '10 at 19:24
  • If that's the case, why not add an array of images as an attribute to Person? – Rizon Dec 09 '10 at 20:56
  • 1
    ... because then all your images (large) would be loaded any time you fetch a Person. That would be bad. The question leads me to believe you literally mean you're putting your images into your Core Data store. For speed and efficiency, you should be storing *references to* the images (along with their metadata) in your store, but the images themselves should be stored separately. This way you're not loading all your person's related images into memory at once. – Joshua Nozzi Dec 10 '10 at 01:15
  • yeah I got what you mean, using an array is definitely bad. But what about using to-many relationship? I believe it uses lazy-loading doesn't it? – Rizon Dec 10 '10 at 10:59
  • Please re-read my comments - the solution I speak of preserves a to-many relationship to an Image entity; the Image entity is best maintained by storing metadata about its represented image and a reference to a file where the actual image is stored. *Do not* store the image itself inside your store... that's just awful (wasteful of resources, poor design, poor performance, etc.). – Joshua Nozzi Dec 10 '10 at 21:04
  • yes I figured it out - thanks! But my question is what makes it that awful? Because if the relationship uses lazy-loading then the images get loded into memory only when I explicitly access the property (i.e. Person.images) – Rizon Dec 11 '10 at 02:02
  • VFAQ. That question has been answered a number of times on SO alone. Google yields even more. Here's an SO community wiki on the subject: http://stackoverflow.com/questions/3748/storing-images-in-db-yea-or-nay – Joshua Nozzi Dec 11 '10 at 04:49
  • Adding: I'd look specifically for SQLite-related discussions though. Maybe iPhone-specific discussions, given the limited system resources... – Joshua Nozzi Dec 11 '10 at 05:01
1

In this case, the datetime the image was added is data that you're interested in, so it should be included in your model somewhere.

paulbailey
  • 5,328
  • 22
  • 35
  • You're meaning was to add "date" attribute to the image entity? Well, I forgot to mention that the user can edit the images list - meaning he can add a new image and determine that it should be the first one (or second and so forth..) – Rizon Dec 09 '10 at 18:45
  • In that case, Rizon, then you'd want to use a separate sortOrder attribute on the image entity as I originally stated in my answer. When the user drag-and-drop reorders a Person's images, you'll need to renumber them by their sortOrder attribute. – Joshua Nozzi Dec 09 '10 at 18:51
  • and each time an image is entered in between - I need to go through all the sequential and increase their sortOrder ? – Rizon Dec 09 '10 at 19:09
  • Or just manipulate the array directly and re-number them all. I added a category on NSArray with a method called -renumberByKey: that simply sets a number with the current index like setValue:[NSNumber numberWithInteger:i] forKey:key] for each member of self. – Joshua Nozzi Dec 09 '10 at 19:21
  • "manipulate the array directly"? Where exactly do I need to have an array? – Rizon Dec 09 '10 at 19:27
  • Sorry - I didn't specify that managing the sort order can't be done via bindings, so this implies code. When you fetch (or ask for a mutable copy of -allObjects of) the related images, you'll have an array of your images. If you move the items within the array directly, you can then just renumber them (by setting a new -sortOrder for each) in a for loop and you're done since Core Data has noted the changes. Just remember to specify sort descriptors when you fetch (or -sortedArrayUsingDescriptors, or however you want to sort the array by your sortOrder attribute). – Joshua Nozzi Dec 10 '10 at 01:23