Modifying managed objects obtained from NSFetchedResultsController - objective-c

I have a simply core data model which has two entities, a Person and a Photo. Person has a one-to-many relationship with Photos. Everything works fine, and when I access the photoList property on Person I get an NSSet with all the photos for that person.
My question is, how can I modify the managed objects in that set and the commit the results back to the core data backstore? At the moment, if I modify one of the Photo managed objects in the set they don't get saved.
The code looks something like this:
Person *myPerson = [fetchedResultsController objectAtIndexPath:indexPath];
[photosController setPhotos:[[myPerson photoList] allObjects]];
Where the set that the photosController gets is perfectly readable, but modifying its content does not update the backend store.
Thanks for all the help

Changes to managed objects are only retained in memory until you save the managed object context of the objects. Once that's done, the changes will be committed to the persistent store.

Related

Need some clarifications on refreshObject:mergeChanges:YES

Some background:
I am trying to store a large amount of data in local DB and I want to do it as efficiently as possible.
Scenario:
There are many entities which are inter-related, such as address is associated with a contact like this:
address <<-> contact
To manage relationships, I have written a method in each subclass of NSManagedObject, below is some code snippet:
// class Contact
- (void)manageRelationships
{
#autoreleasepool {
LocalDBManager *localDBManager = [[LocalDBManager alloc] init];
// managing relationships
// map associated addresses
NSPredicate *addressIdPredicate = [NSPredicate predicateWithFormat:#"%K == %#",ADDRESSID,self.addressid];
// below method returns an object as fault by firing a fetch request against context
NSSet *retrievedAddresses = [localDBManager retrieveManagedObjectsForEntity:ADDR_ENTITY withPredicate:addressIdPredicate asFault:YES withPropertyValues:NO error:nil];
self.addresses = retrievedAddresses;
// managing few more relationships
}
}
Point to consider:
Since there can be multiple relationships for an object, I know that memory consumption will increase when I will be mapping relationships.
Question:
I want to turn back an object into fault, without loosing any changes made, once the relationships are mapped.
From apple documentation and some googling I came to know that I can use refreshObject:mergeChanges: method. So I am planning to add below line at end of code block in manageRelationships method:
[[self managedObjectContext] refreshObject:self mergeChanges:YES];
I am a bit confused and want to know that -
Does it mean that whatever changes were made to the object will be
stored in persistent store and then the object will turn to a fault?
If yes, then can I consider it equivalent to save method of
NSManagedObjectContext
Please suggest.
First of all you do not need to manage relationships by yourself. Let CoreData handle that.
Core Data automatically resolves (fires) the fault when you access data in the fault. This lazy loading of
the related objects is much better for memory use, and much faster for fetching objects related to rarely used
(or very large) objects.
CoreData performance
You might do this by simple instantiating one-to-many relationship between contact-address.
Regarding to refreshObject:mergeChanges: you are wrong. It is not an equivalent to save: method. If you set merge changes to YES it only means that:
If flag is YES, then object’s property values are reloaded from the values from the store or the last cached state then any changes that were made (in the local context) are re-applied over those (now newly updated) values.
Cocoa touch Doc
So if you did some changes in managed object A and then did [context refreshObject:A mergeChanges:YES] than object A would still remain in an unsaved state.

CoreData: how to leave particular objects in context unsaved and save others?

Prerequisites:
I have 2 methods in the network API:
return list of entities (just basic info: name, id, etc.)
return detailed info about entity
The requirement is to save only objects created by processing the second request (save to sqlite) and leave non-full objects without saving.
Also, the 'main' context should contain only full objects from 1st request, and any other 'temporary' context should contain all the others objects.
I've tried to create two instances of NSPersistentStoreCoordinator and use them for different types of contexts, but it seems that for one NSManagedObjectModel can exist only one coordinator (the pointer points to the same adress).
If I understand you correctly, then I think your best option is to only create a managed object once you're sure you want it to persist in Core Data storage. You may need another layer of non-managed objects to contain data for the "non-full" entities
(This would be something like Data Transfer Objects from Java EE programming.)
You can not save indiscriminately from within the same MOC. Saving the MOC always saves everything in it.
So, you can use a separate MOC that is never saved, and then just "move" those objects to the main MOC when they are ready to be saved.
The solution that exactly solves my problem is to create two 'forks' of core data stack:
one with default config and mainContext
the second (new instance of the same NSManagedObjectModel, new
NSPersistentStore (inMemory) and new NSPersistenStoreCoordinator )

Accessing deleted objects in iCloud notification

I have an app set up much like the iCloudCoreDataRecipes sample (ie, using Core Data in conjunction with iCloud). In the app delegate, I observe the
NSPersistentStoreDidImportUbiquitousContentChangesNotification
When a notification arrives, I call
[context mergeChangesFromContextDidSaveNotification:note];
I have some additional processing I'd like to do when this notification is received but am having trouble using the objects identified by the NSManagedObjectID's present in the NSDeletedObjectsKey set.
NSSet *deletedObjects = [info objectForKey:NSDeletedObjectsKey];
for (NSManagedObjectID *oid in deletedObjects) {
NSManagedObject *obj = [context objectWithID:oid];
}
If I access any property on the obj, it is nil.
I then tried running the above code prior to calling mergeChangesFromContextDidSaveNotification:
When I did that, I was able, most of the time, to access the properties on the object. In some cases, I'd get an exception for unable to fulfill fault; the record was already deleted from the Core Data store.
I realized that accessing the deleted object's properties would work if the object had been loaded into the context some time prior to the notification arriving (ie, if the object was viewed/accessed within the app).
My problem is that I'd like to do some clean-up related to the deleted objects; my NSManagedObject's have a property that I'd like to read and then use to perform some work outside of Core Data related to that value.
What am I missing? Is it possible to do this?
You should probably look at
- (void)prepareForDeletion;
and override that in your NSManagedObject subclass.

Cocoa Core data filename?

I followed Apple's example for creating a managed object which btw was great...
http://developer.apple.com/cocoa/coredatatutorial/index.html
However I now want to know what "name" (filename) the user saved his data as. Does anyone know how to pull the filename from the core data object.
something like this would be great...
NSLog (#"the filename is %#", [coreData filename]);
Any ideas?
Managed objects have no inherent relationship with files; there's nothing saying they ever need to go in to or come out of a file at all.
In the case that they are, you'll be wanting to look at the NSPersistentStore object eventually associated with your managed object through its managed object context and persistent store coordinator.

Retrieving All Of An NSTreeController's Objects

Bit of Background info, I'm using An NSOutlineView with Core Data.
This Is What I'm trying to do:
Retrieve All The objects from the Outline Views Tree Controller.
Retrieve the 'name' Property (Core Data) from each of these objects as a String.
Finally store the Strings of the 'name' Property from all the Objects in an NSArray.
For extra help, here is a Picture of my Core Data Model, http://snapplr.com/xqxv
Is this possible?
You don't need to go to the treeController to get your objects, you can query your ManagedObjectContext directly.
You essentially create and execute a fetch request, which returns an NSArray. You set the predicate for the fetch in this process as well, so if you are using it to try and filter your data this is useful as well.
Here is the example from the Apple Documentation on Fetching Managed Objects.