views:

518

answers:

3

I'm trying to decide whether some application state, specifically the selected item in a list, should be stored in Core Data or NSUserDefaults.

Generally I believe that application preferences and state should persist in NSUserDefaults, and model-level data should persist elsewhere, say in Core Data. My model so far is:

  • Should the data be stored at all? If the user wouldn't reasonably expect it to be, then throw it out (for example, the cursor position is not saved in TextEdit)
  • NSUserDefaults:
    1. If the application were multi-document, the setting would apply to all documents
    2. It's conceivable that the data would be configured in preferences
    3. Having the data outside of the model makes sense for testing (swapping several defaults with one model store)
  • Model-level
    1. The data clearly belongs as an attribute of a model-level object
    2. The data is sufficiently large that storing it in NSUserDefaults would cause performance problems
    3. It would be difficult or time-intensive for the user to re-create the data (they would definitely consider the loss of this information "data loss")

I plan to store the sort order of some entities in Core Data. Without this information (i.e. a "sortIndex" or "order" attribute) each entity instance would have to be augmented with data from the user defaults.

However, storing state in the model seems like a slippery slope. If I store sort order then it also seems appropriate to store selection since they are both the state of a list. The selection data for my use case may actually be quite large. Specifically, the icons in one list depend on the selection in each of their sub-lists.

Does anyone have a hard line they draw with respect to NSUserDefaults vs. data model?

+5  A: 

You didn't mention whether this is a document-based app (like say, TextEdit) or a library-based one (like say, AddressBook).

That may help you decide where such information should go: assume a document-based app. Assume its documents get placed under version-control (this is actually feasible when using Core Data's XML data store type). Open the app, change the doc's sort orders. Does this dirty the document? Would this change be worth a check-in? Would the change be valuable to other users of this repository?

Typically, sort orderings aren't valuable enough to warrant document-based storage (ala NSTableView's Auto Save Name in Interface Builder). But your app may place a priority on sorting (it sounds like it).

So, there is no hard-and-fast rule. But I think the idea of having a document under version control, potentially shared with others, provides a good intellectual framework to make your case for either side.

rentzsch
It's an iPhone app which in my case falls under the library-based scenario. I like the mental model of considering a hypothetical multi-document app though, and whether the change would make the app dirty. In my case it would, since the selection of a sub-list changes the view of the higher list (specifically, the sub-selection changes what image is shown next to an item in the higher view).Regarding sorting, I meant that the sort order is user-defined. That is, they can arbitrarily order the list (like creating a playlist in iTunes).
orque
Building on the "does it dirty the document" I'd also like to add "would the change to the data result in an addition to the undo stack". Undo works for both document-based and library-based apps so it seems like a nice heuristic.
orque
+2  A: 

I agree with rentzsch, but another way to view it:

Is the selection part of the data or is it metadata? If metadata, is it metadata about a single document or is it state that should apply to any document that happens to be opened next?

Document-specific metadata might want to be stored as an extended attribute. For example, TextMate stores the selection for a document this way, much as BBEdit, MPW, and others used to store tab settings, window size, etc. as a resource in the resource fork. Metadata is considered optional and the document is intact if it is stripped away.

If the selection is an integral part of the data, then by all means store it in the data, using Core Data if you happen to swing that way.

And if it's not a document-based app, then NSUserDefaults is the simplest path since support for it is generally built into common NSView subclasses via bindings.

ohmantics
I agree. I forgot to state what my existing model was, so I fixed up my question (I believe that is the "right thing" to do here)I was having a hard time deciding whether the information is an "integral part of the data". With Rentzsch's model (would I display the dirty-dot) this becomes easier,
orque
+1  A: 

I personally don't have a hard line between saving preferences in the file itself or in NSUSerDefaults.

But I have always tended towards the obvious:

  • Application preferences = NSUSerDefaults
  • Document preferences = in the file itself

For selection state specifically, I would judge if keeping that is important enough to the user. If it is, and important enough to move with the document to another computer, I would keep it in the document itself.

If it isn't important (or applicable) I wouldn't bother with saving it at all.

Lucien
I think this was tripping me up because on iPhone I don't necessarily consider any apps as having "documents"; it's all just data. Saving state becomes much more important since switching applications means quitting and relaunching.
orque
I think even in an iPhone app - if the section state in the users current location is important to the data, I'd save it, if not, I wouldn't bother. Sounds like it might be, so I'd save it with the data.
Lucien