How to have different NSManagedObjectContexts? - objective-c

I have only one database model schema in my app, so IMHO, NSManagedObjectModel and NSPersistentStoreCoordinator objects might reside in main app delegate class for accessing from other parts of the app. However, I would like to have different NSManagedObjectContexts objects for various parts of my app because I will use multithreading.
From my personal database experience, I assume NSManagedObjectContext is somehow similar to the concept of database transaction. So, it's logical to have separate context objects for various multi-threaded parts of my app in order to avoid committing unwanted changes from one app part to another. When creating new project with enabled for core data, Xcode creates three essential methods in main app delegate
- (NSManagedObjectModel *)managedObjectModel{
// reads your database model file and defined entities from defined DataSchema.xcdatamodeld file
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
// uses already read database model and initializes defined sqlite database file and returns a persistent store coordinator - a pointer to the database
}
- (NSManagedObjectContext *)managedObjectContext{
// opens a connection (and transaction) to the database.
}
So, the question would be, is it reasonable to leave persistentStoreCoordinator and managedObjectModel methods in main app delegate (and access them through the app), but to move managedObjectContext method to those classes that need private data handling?

You're always going to have one main managed object context that runs on the main thread.
If you're doing background processing on another thread, you can create another NSManagedObjectContext on a background thread, pointing at the same NSPersistentStoreCoordinator.
When you save/delete/update in the background context, notifications are fired that you listen to on the main thread, and merge the changes back into the main context.
Personally, I don't have any Core Data objects in the App Delegate, because I don't think they belong there. I think Apple use that in their examples for simplicity of the example. I usually have a CoreDataStack object that is passed around where I need it.
You could look at a higher level Core Data API, such as Magical Record. I've just started using this and it's pretty useful, and removes a lot of the boilerplate code you get from Core Data. It's written by Marcus Zarra and team, a guy who apparently knows a lot about Core Data.
In iOS 5, Core data was improved by allowing ManagedObjectContexts to have a parent context. So in your case, your background contexts would be children to the parent context, and apparently it's a lot easier to merge back in. I haven't tried this yet though.

So, it's logical to have separate context objects for various
multi-threaded parts of my app in order to avoid committing unwanted
changes from one app part to another.
It is possible to have multiple contexts, which is a practice used widely.
is it reasonable to leave persistentStoreCoordinator and
managedObjectModel methods in main app delegate (and access them
through the app), but to move managedObjectContext method to those
classes that need private data handling?
You can leave it in the app delegate, accessing it via [[UIApplication sharedApplication] delegate].
You could create a separate singleton class containing the core data stack.
You could just pass a pointer to the managedObjectContext between classes.
Each viewController could create it's own context linking it to a parent context via setParentContext:.
As you can see it really depends on the complexity of your project. Generally if you have to a lot of specific retrievals and saves you might want to stick the Core Data stack in it's own class. For smaller projects why not just leave it in the app delegate and pass the context via a pointer.
Also, check out the 2011 WWDC session about Core Data. It talks about a bunch of cool new features.

Related

Does accessing a property on an NSManagedObject from a background thread make the context cross that thread?

I need to use a property on my NSManagedObjectContext as a parameter in a method that runs in the background. After this method is called I then have problems from that point forward with that context even though all I did was get a property value.
From the docs:
Any time you manipulate or access managed objects, you use the associated managed object context. Core Data does not present a situation where reads are “safe” but
changes are “dangerous”—every operation is “dangerous” because every
operation has cache coherency effects and can trigger faulting.
I've been working with Core Data in multi-threaded apps for some time (also in pre-iOS 5 era, without parent contexts etc.). I suspect it does some threading voodoo (locks and stuff) under the hood. If you want to be 100% safe, in a background thread you can't call any method on a NSManagedObject if its NSManagedObjectContext has not been created on the same thread. Otherwise, Undefined Behavior may happen (I got some deadlocks, for example).

Singleton Instance vs Class Methods

While recently working with Objective-C and various libraries written in it, I've noticed two really popular singleton patterns. One version fetches the singleton instance and calls its instance methods and other version only exposes class methods and never gives you an instance to work with. All have the purpose of abstracting access to a single resource (StoreKit, CoreData, Parse API etc.). For example, here's the former approach used in MKStoreKit:
// initialize singleton during app boot
[MKStoreManager sharedManager]
// sometime later in the app
[[MKStoreManager sharedManager] buyFeature:kFeatureAId
onComplete:^(NSString* purchasedFeature)
{
NSLog(#"Purchased: %#", purchasedFeature);
}
onCancelled:^
{
NSLog(#"User Cancelled Transaction");
}];
or alternatively NSUserDefaults, UIApplication etc.. The other approach can be seen in MagicalRecord or here with Parse API:
// configure API credentials sometime during app boot
[Parse setApplicationId:#"123456"
clientKey:#"123456"];
// sometime later
PFObject *testObject = [PFObject objectWithClassName:#"TestObject"];
[testObject setObject:#"bar" forKey:#"foo"];
[testObject save];
What are some pros and cons of the two approaches and is one of them fundamentally better than the other?
Not having to retrieve the shared instance saves some screen estate (the performance difference is likely irrelevant), but am I screwing myself in some other way, for example, testability-wise?
Thanks!
There are two different ways to implement the approach based on class methods:
Make a singleton instance using a class hidden from everybody, and hide its methods behind wrapper class methods with identical signatures, or
Make class methods that do all the work
The implications of the first implementation are that everything you can do with a singleton, you can do with the hidden singleton:
using a subclass becomes a possibility
switching the instance in the middle of the run is easy
the state lives in instance variables
initialization follows the familiar pattern
If you go for an implementation that does not use a singleton, you would be relying on static variables to keep your current state. That is a legitimate choice, but the initialization pattern becomes different (perhaps even using a dispatch_once), you cannot switch the implementation in the middle without relying on some ugly if conditions, and using a subclass becomes a lot more tricky.
Testing the first implementation is somewhat easier than testing the second one, because you can provide a separate implementation of the singleton for testing, perhaps through the back door; with a static-based implementation, this route cannot be taken.
To summarize, I would use a singleton-based solution, with the singleton optionally hidden behind a "facade" that provides access to singleton's methods. I would not use an implementation where all state must be placed in static variables.
One advantage of the singleton approach is that it becomes trivial to allow other instances if you need to. If you take the class method approach, that's all you get without a lot of refactoring.

Avoiding coupling in a document-based Cocoa app?

I'm new to Mac programming and I'm working on a document-based application.
My NSDocument subclass creates a NSWindowController subclass. This window controller creates two NSViewController subclasses as well.
Sometimes, a change in one of the views of a NSViewController needs to notify the NSDocument and/or the main model class. Also, a change in the model needs to be notified to every/some view(s).
My question is: what is the best approach so that there is no (or minimum) coupling? I know there are several choices, but I'm not sure which one suits best for my application as I'm newbie not to programming but to Cocoa and especially NSDocument:
KVO. Looks nice and easy to implement, but I don't like the idea of not explicitly notifying the observer(s) about a change (AFAIK, self.someProperty = newValue does automagically notify observers), and don't like the fact that you have to register to property names which could change in time.
Notifications. I know what they are and I've used them for iOS. But I've read somewhere that they are not guaranteed to be sent immediately to observers. Is it true? If not, do you see them as a good approach for a document-based app?
Delegates. Yes, under normal conditions (or what I've usually seen), a class has one delegate. But creating an array of delegates works as well (just tested it). The problem I see here is that every time I need to notify the delegates I have to loop through them, make sure they respond to a method, and call that method.
Are there any other alternatives I'm missing?
KVO by a controller class is the most common way to do coupling between a model and its view(s). In fact, Cocoa Bindings, which are intended to mostly eliminate code in the controller layer, are based on KVO. It is true that KVO/KVC relies on property names, and that if those change, you'll have to change the bindings or KVO setup connecting your view. However, it's not usually feasible to make your views completely unaware of the underlying model specifics, so I don't see this as a problem.
My recommendation would be to use Cocoa Binding where you can, as they eliminate a lot of glue code. In places where they can't be used, your controllers (the middle layer in MVC) should use KVO to observe model changes and update the appropriate views. Changes in the views can be passed back to the model via property accessors and/or KVC by the controllers.
Yes, under normal conditions (or what I've usually seen), a class has
one delegate. But creating an array of delegates works as well (just
tested it).
Delegates are often used to modify the behavior of the delegating object. An application delegate is a good example: NSApplication by itself isn't very interesting; it relies on its delegate to define the interesting behavior of the application. Having multiple delegates all trying to modify the behavior of a single object could be a problem if the various delegates conflict with each other. What do you do if the delegates disagree?
There are some cases in Cocoa where a class uses more than one delegate, but each one has a separate role. For example, NSTableView has both a delegate and a data source, but both are really delegates of a sort.
The problem I see here is that every time I need to notify the
delegates I have to loop through them, make sure they respond to a
method, and call that method.
That's not hard to solve. For example, you could create an NSInvocation to encapsulate the call, and then send the invocation to each "delegate." However, if you do that you'll have nearly reinvented the notification system. If you need the one-to-many communication that you'd get with your multiple delegates proposal, you'll probably be better off using notifications or KVO.

Core Data singleton manager?

What technical reasons are there not to make a singleton class to manage my Core Data? I'm trying to make a decision now, if I should strip out all of the boilerplate core data code and re-implement it in a singleton.
The boilerplate code in the application delegate in the Xcode templates is functionally implemented as a singleton. The application object is a singleton and it maintains but one delegate object so you've only got one instances of the Core Data stack and since the application object is universally accessible, you can always get to the app delegate as well.
However, even that works only for simple apps with one persistent store with all the context using that one store. In more complex apps you may have multiple stores or context so a singleton quickly becomes too bloated.
A singleton usually won't buy you much complexity hiding or save duplicate coding because most of the coding you have to do with Core Data is in the controller layer where you link up the model to the view/interface. Since that logic is usually custom to each view, you can't actually park it in the singleton.
I've used singletons in the past but in the end they usually prove more hassle than they are worth.
There are two important considerations (note these are not the only two) when deciding if a singleton is right for you:
Threading
Memory Usage
Threading
Singletons are convenient, but if your application uses multiple threads you might be tempted to write something like this:
[[CDSingleton managedObjectContext] executeFetchRequest:someFetch];
//later on a background thread you might write
NSManagedObject *object = [[CDSingleton managedObjectContext] objectWithID:objectID];
Shortly after that, your application will crash because you've accessed a managedObjectContext which was likely created on the main thread from some other thread.
Memory Usage
Singletons never go away, that's the point of a Singleton. Thus, they also never willingly free their consumed resources. In the case of CoreData that means the managed object context will continue to hold managed objects in memory until you call -reset or -save:.
That could be bad if your app uses a lot of data.
Best practice is to pass the managed object context between view controllers. Apple documentation and samples do that. You should never really have to access your app delegate, not for Core Data, not for anything.
http://www.cimgf.com/2011/01/07/passing-around-a-nsmanagedobjectcontext-on-the-iphone/

How or where should I store object instances that I require globally within my iOS app?

I'm building an iOS application. Most of the application requires access to a persistent object. This object is instantiated when the app loads via the Application Delegate.
The problem I have is that numerous View Controllers that need to access this object.
What is the best way and best practice to create global objects that can be access from anywhere in the application?
Examples would be appreciated. Many thanks.
You might want to look at the Singleton pattern. The linked article provides a pretty good description of it including how to implement one in Cocoa.
If the Singleton doesn't make sense in your context, and you still need the Global reference to your variable, you could just put a reference to it in your AppDelegate. (Not recommended)
It can be accessed from within your application anytime using:
[UIApplication sharedApplication] delegate]