I'm using CoreData in my latest iPhone app. I find it complex at the beginning but I guess this is the best choice when you need to store objects in an iPhone app (http://inessential.com/2010/02/26/on_switching_away_from_core_data).
Is there any best practices when using CoreData in an iPhone app? For example, I don't want all my controllers to deal with this NSManagedObjectContext that you need when you want to make requests. Do you define a class just for CoreData requests?
Use Core Data to save your application's permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.
The next time you need to store data, you should have a better idea of your options. Core Data is unnecessary for random pieces of unrelated data, but it's a perfect fit for a large, relational data set. The defaults system is ideal for small, random pieces of unrelated data, such as settings or the user's preferences.
Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.
Even though Core Data knows how to use a SQLite database as its persistent store, that doesn't mean you can hand it any SQLite database. The database schema of the SQLite database used by Core Data is an implementation detail of the framework. It isn't publicly documented and liable to change.
I usually create a dedicated object to manage my Core Data stack and related objects and behaviors. This is useful because there is a lot of boiler plate with Core Data so I can make a generic base manager class and then use a subclass for each app. I usually call it AppNameDataModel.
I prefer to hide the managed object context inside the DataModel object. This forces the other objects in the app to ask the DataModel object for access to the Core Data stack which gives good encapsulation and safety.
Usually, I create methods in the DataModel class to return fetches for entities e.g.
-(NSFetchRequest *) entityNameFetch;
... and then have a performFetch
method in the DataModel. In use, a controller ask for a fetch for an entity, configures the fetch and then ask the DataModel to perform the fetch and return the results. You can script the generation of the methods that return the fetch and the perform fetch is boiler plate as well. This all saves a lot of time especially when prototyping.
A reference to DataModel instance itself can be passed from controller to controller but I think this is a valid use of the singleton pattern so I often make the DataModel a singleton and the provide a category on UIViewController for a property to access it. That means that any view controller I add to the project automatically has access to the DataModel.
This pattern keeps everything nicely encapsulated and modular. It makes it easy to add new views or to share the data model between projects. It takes a little work to set up initially but once you have the base class, future use is massively sped up.
Thanks Brad for pointing to this question.
As mentionned on Apple documentation [1], the context have to be passed to each new view controller that need CoreData.
On iPhone:
By convention, you can often get a context from a view controller. It’s up to you, though, to follow this pattern. When you implement a view controller that integrates with Core Data, you can add an NSManagedObjectContext property.
A view controller typically shouldn’t retrieve the context from a global object such as the application delegate. This tends to make the application architecture rigid. Neither should a view controller typically create a context for its own use. This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.
When you create a view controller, you pass it a context. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.
[1] - http://developer.apple.com/iphone/library/documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html#//apple_ref/doc/uid/TP40008283
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With