Modeling user-orderable lists with Core Data / Bindings
I'm working through a learning project around Core Data on OS X. I have an entity (Foo) in the data store, and in the UI, I use an NSArrayController with bindings to put some (name) field of the Foo objects into an NSTableView, where the user can add/delete/rename (and potentially reorder) the items.
As you know, Core Data storage is unordered. However, I'd like to give it order from the user standpoint. E.g. adding a new row to the table view fixes that new Foo to the end of the list, etc. If the table allows reordering, that order is maintained.
I assume that I should accomplish this by adding some hidden (ie the user never encounters it) "ordinal" field to the Foo entity, which is fine. I'm trying to figure out:
- Where is the right place to set this "ordinal" field for new it开发者_StackOverflow中文版ems? Right now, a button is invoking the
add:
action on the array controller and bindings handles all the rest magically. (I'll need access to the count of items to set it correctly.) - Where is the right place to fixup the whole result set's ordinals on delete or reorder?
- Assuming all objects in the store have a reasonable ordinal attribute, what must I do to the UI connections to get the table view to display the results sorted by that ordinal? Is this something I can do purely with bindings? Do I need to subclass... something?
It feels like this is a common enough scenario that people here might have a ready answer. I'm new to Core Data and bindings-- trying to grope my way around. Don't need code; pointers in the right direction would be great. Thanks.
The simplest way to do ordering is to make sure that your entity closely models the data the user actually needs. Remember, Core Data is not a database system. It is an object graph management system with persistence options. Objects have behaviors. That means that you can put a lot more information into Core Data than you normally would for just a database.
A big part of the time, ordering comes naturally by good entity design. For example, the user needs to order Foo objects by when they were added to the graph. Therefore, the Foo object needs a creationDate
attribute. Just bind a sort descriptor on the creationDate
attribute and you are done.
The biggest challenge is arbitrary ordering that has nothing to do with data being modeled. I like to solve this issue with a lightweight Order
entity that relates to the actual ordered entity.
Foo{
name:string
creationDate:date
order<-->Order.foo
}
Order{
foo<-->Foo.order
previous<-->Order.next
next<-->Order.previous
}
As you can see, the Order
entities function like an old school linked-list. To insert a new Foo
object in the order, just insert a new related Order
object in between to existing Order
objects. To create an ordered list, just start with Order
object whose previous
attribute is nil and then walk the next
relationships, pulling each foo
relationship as you pass.
There are other variations.
But again, entity design is always best. An entity is meant to model/simulate a real-world object, event or condition. If you think about the real-world thing you want to simulate and then include that in the entity and object graph design, then quite often your ordering occurs naturally.
精彩评论