Category: Base&inter&skill iphone platform iphone+ platform 2014-03-24 15:27 1140 People read reviews (1) favorites report
directory (?) [+]
Core data is an important part of iOS, which can be understood as an ORM implementation based on SQLite (or, of course, other storage, such as In-memory, which is only common to sqlite), so there are characteristics of relational databases and no need to write SQL. By the way, the official statement is that using core data can reduce the amount of code by 50%-70%, but believe that the people who used it should understand that core data is cumbersome to use, which is why there are a number of third-party libraries to replace/two-pack Core data.
A slightly more complex application may have the possibility of processing multiple copies of data simultaneously, which requires multithreading core data. Prior to IOS 5, the official recommendation was to use "thread confinement", where each thread used a separate MOC (managed object context) and then shared a PSC (persistent store coordinator). While passing data between threads, pass Objectid, not object, because the former is thread-safe and the latter is not.
If the cud (Create, update, delete) operation is performed on the PSC in a thread, how does the other thread perceive it? This is done by listening to events. For example, the "nsmanagedobjectcontextdidsavenotification" event is monitored in thread A, and if the cud operation is performed in threads B, thread A can perceive and trigger the action of the response, although it can be noti UserInfo to get managed objects, but because they are associated to another MOC, they cannot be manipulated directly, and the workaround is to call the "mergechangesfromcontextdidsavenotification:" method.
In a picture, this is basically the case:
- (void) _setupcoredatastack{ // setup managed object model nsurl *modelurl = [[nsbundle mainbundle] urlforresource:@ "Database" withextension:@ "MOMD"]; _managedobjectmodel = [[nsmanagedobjectmodel alloc] initwithcontentsofurl:modelurl]; // setup persistent store coordinator nsurl * storeurl = [nsurl fileurlwithpath:[[nsstring cachespath] stringbyappendingpathcomponent:@ "Database.db"]]; nserror *error = nil; _persistentstorecoordinator = [[nspersistentstorecoordinator alloc] initWithManagedObjectModel:_managedObjectModel]; if (! [_persistentstorecoordinator addpersistentstorewiThtype:nssqlitestoretype configuration:nil url:storeurl options:nil error:&error]) { // handle error } // create moc _managedobjectcontext = [[nsmanagedobjectcontext alloc] init]; [_ managedobjectcontext setpersistentstorecoordinator:_persistentstorecoordinator]; // subscribe to change notifications [[ Nsnotificationcenter defaultcenter] addobserver:self selector: @selector (_mocDidSaveNotification :) name:nsmanagedobjectcontextdidsavenotification object:nil];}
look again at notification Handler, the main role is to merge new changes.
- (void) _mocdidsavenotification: (nsnotification *) notification{ nsmanagedobjectcontext *savedcontext = [notification object]; // ignore change notifications for the main MOC if (_managedobjectcontext == savedcontext) { return; } Dispatch_sync (Dispatch_get_main_queue (), ^{ [_managedobjectcontext mergechangesfromcontextdidsavenotification:notification]; });}
This approach is a bit cumbersome to implement and maintain, so there's a more convenient and flexible implementation in iOS 5, which is "nested moc".
[[Nsmanagedobjectcontext alloc] initwithconcurrencytype:nsmainqueueconcurrencytype];
You can see that Concurrencytype can be selected at initialization, and there are 3 options:
Nsconfinementconcurrencytype
This is the default item, each thread is a separate context, primarily to be compatible with the previous design.
Nsprivatequeueconcurrencytype
Create a private queue (using GCD) so that the main thread is not blocked.
Nsmainqueueconcurrencytype
Creating a main queue, using the main thread, will block.
Another important change is that the MOC can specify the parent. With the parent, the cud action bubbles to the parent. A parent can have more than one child. The parent can also have a parent.
Because the UI-related data must be fetched on the main thread while avoiding the I/O operations of the database blocking the main thread, the following model is available:
One of my confusion about this realization is that the child cannot know the change of the parent, that is, if Nsfetchedresultscontroller binds the main MOC, when background Write MOC save, Why would nsfetchedresultscontroller know? Ask for advice.
This is a little bit simpler and clearer than "thread confinement". However, it is recommended to use Magicalrecord, because it is easier to implement, and then write an article when you are free.
Wrote a demo using this model, with TableView and Nsfetchedresultscontroller, interested can look under: Https://github.com/limboy/coredata-with-tableview
2013/06/17 Update
The previous confusion has been eliminated, regardless of the NSFetchedResultsController
PSC, as long as the bound MOC has an save
action, NSFetchedResultsController
it will be notified, regardless of whether the operation has been save
written to the persistence layer.
CoreData in-depth understanding 4--Summary (thread safety vs. synchronous--ios5 before and after)