Adding multiple entries to a set while preserving the object-link
I have a question regarding the addition of multiple CoreData entries in multiple tables.
I have the following code:
while((item = [enumerator nextObject]))
{
DOCategory *cat;
cat = [[self categoryController] getNewCategory];
[cat setName:[item objectForKey: @"name"]];
[cat setDesc:[item objectForKey: @"description"]];
[cat setLastUpdate:updateTime];
//[[self categoryController] commitChanges];
}
I used to call the commitChanges after each enumeration, and that works, but takes a long time, especially on older devices as the initial load is quite substantial. Therefore I just want to save at the end of the whole operation.
What is the best way to add all those objectors to a NSSet (or NSArray) while preserving the link to the ManagedContext. Normally I would 'copy' them into the set, but that doesn't work here. A simple question, just have a block to seeing the best solution.
(I assume that I don't have to 'commit/save' after every new object I created, so the resu开发者_开发技巧lts are not written to the database yet, but are available for searches as there are different relational objects in the procedure)
Update: After the suggestion below and more testing, it appears to me that when I haven't saved/committed the context it is not included NSFetchResultController. Is this right and supposed to be the way? Is there a way to do all the operations (including searches to create relations) in 'cache' and then commit once all is done?
Update 2: In order to get the Managed Object I have a procedure in the Controller-class:
- (DOCategory *) getNewCategory{
return (DOCategory *)[NSEntityDescription insertNewObjectForEntityForName:@"Category" inManagedObjectContext:managedObjectContext];
}
It appears that the code runs fine, including cross references, until I come to adding the final object which uses all the other managed objects. There must be some problem in that code.
Your code is old school Objective-C 1.0 so it would be best to update it. You seldom use enumerators directly like that anymore.
The best way to handle this is to create the new managed objects by inserting them into the context using +[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:]
this both creates the managed object and makes the context aware of it. The context will retain the managed object itself. That's were the "managed" of "managed object" comes from.
The normal practice when making a lot of changes is to change all the objects and then save the context only when you are done making all the changes.
Update:
It appears that the code runs fine, including cross references, until I come to adding the final object which uses all the other managed objects. There must be some problem in that code.
That sounds like you might have a problem with the relationship being set properly in the data model itself. I can't say for certain without knowing what your data model looks like.
I discourage the use of cast with insertNewObjectForEntityForName:
e.g.
(DOCategory *)[NSEntityDescription insertNewObjectForEntityForName:@"Category" inManagedObjectContext:managedObjectContext];
... because if you have a data model problem, such as not providing the name of the DOCategory
class for the DOCatergory
entity, the cast will obscure the problem. If there is no class defined the method will return an instance of the generic NSManagedObject
class or if you accidentally define the wrong class for the entity e.g. MadeUpClassName
instead of DOCategory
then the cast will force the runtime to treat the returned object as a DOCategory
object. That might work fine until way down in the code.
...it appears to me that when I haven't saved/committed the context it is not included NSFetchResultController. Is this right and supposed to be the way? Is there a way to do all the operations (including searches to create relations) in 'cache' and then commit once all is done?
Not exactly sure what problem you are seeing. It is best practice to make all changes to all objects and then to save the context instead of saving after every change to any single object. Disk operations are expensive.
If your changes to the context are not reflected in the NSFetchResultsController (FRC) then you most likely did not implement the FRC delegate methods that update the tableview (see FRC docs.) Another possible error is that you've created two context accidentally. If you are using threads, each with a separate context (required practice) then you have to merge the background context with the front context before the changes made in the background are made known to the foreground.
精彩评论