views:

134

answers:

3

In a previous question, I was looking for an alternative to modifying how "no date" was being stored in the date attribute of my NSManagedObject subclass. Previously, I had assigned nil to that attribute when a user didn't assign a date. In order to address sorting issues when using NSFetchedResultsController, I have decided to assign [NSDate distantFuture] to the date attribute when a user doesn't assign a date. However, given that this app is already in the wild, I need to update the Core Data store such that any existing nil date values are changed to [NSDate distantFuture].

What is the best way to make this change? The first thing that comes to mind is to iterate through all of the objects in the store in an array and change any nil values that are found. This could be limited to a one-time event by checking against a user defaults key that indicates whether this upgrade has been performed. Is there a way that I can do this with Core Data versioning instead? Or another method that doesn't involve me writing throw-away code?

A: 

I guess there are other methods but a one off fix thow away code and a flag in defaults is probably the most efficient. You could check for nil in the dates to trigger the code but defaults is going to be quicker for non-trival data volumes.

Andiih
+2  A: 

If you're releasing an update, consider creating a new version of your model. Set the date property to required (non-optional) and provide a distant future date as the default value. Core Data will fill in the default values for the currently nil date once during the migration process from the old currently shipping model to the new soon-to-be-released model.

This also avoids code being written by the developer; I'm lazy so that path is really appealing to me.

Giao
A: 

Use a fetch request with an NSPredicate that matches only nil values for the NSDate attribute you want to adjust. Instead of performing a fetch, use -[NSManagedObjectContext countForFetchRequest:error:]

That will be much quicker than executing the fetch, and if you get a non-zero result, continue and execute the fetch, but don't fetch properties you don't need, and don't fetch relationships. If the count is really big, set the fetch batch size to keep the high-water-mark on your memory usage to a minimum.

ohhorob