There are quite many questions about this kind of question, but I can't find any for CoreData. The problem is: I want to update a large amount of NSManagedObject (you can think of resetting a property's of a large amount of NSManagedObject).
Right now, all I can think of is:
- Fetch all object.
- Loop through all of it, using forin-loop.
- Setting the property in each for block.
The data might be large, and I also want to write a Utility for this action. So the question is:
Is there any more efficient way to perform this? I don't believe using for-loop is efficent.
BONUS QUESTION
Also, I would like to delete all object that satisfied a condition (most likely a boolean flag). My solution is rather simple like the one above:
- Fetch all object, with NSPredicate and condition.
- Loop through all, forin.
- Delete each one of it.
Same question for solution.
The real problem
The real problem is, I want to set all the object's flag (call it willDelete) = YES. Then synchronize from server, then update them and set willDelete = NO. After that, whichever has willDelete = YES would be delete from context.
EDIT 1
My question might be different this one. I want to update the property first. And I care about performance time, not the memory.
EDIT 2
Okay, I managed to use NSBatchUpdateRequest. But the problem is: I got nsmergeConflict. Not sure what to do with this progress. Here's the code anyway:
- (void)resetProductUpdatedStatus
{
NSBatchUpdateRequest *request = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:NSStringFromClass([Product class])];
request.propertiesToUpdate = @{@"hasUpdated" : @(NO)};
request.resultType = NSUpdatedObjectIDsResultType;
NSBatchUpdateResult *result = (NSBatchUpdateResult *)[[CoreDataUtil managedObjectContext] executeRequest:request error:nil];
[result.result enumerateObjectsUsingBlock:^(NSManagedObjectID *objId, NSUInteger idx, BOOL *stop) {
NSManagedObject *obj = [[CoreDataUtil managedObjectContext] objectWithID:objId];
if (!obj.isFault) {
[[CoreDataUtil managedObjectContext] refreshObject:obj mergeChanges:YES];
}
}];
}
This will set all hasUpdated
= NO. Next, I'll perform the sync progress. With all the products caught from the synchronization will update the hasUpdated
= YES. Next perform delete:
- (void)updateProductActiveStatus
{
NSBatchUpdateRequest *request = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:NSStringFromClass([Product class])];
request.predicate = [NSPredicate predicateWithFormat:@"hasUpdated = NO"];
request.propertiesToUpdate = @{@"isActive" : @(NO)};
request.resultType = NSUpdatedObjectIDsResultType;
[[CoreDataUtil managedObjectContext] executeRequest:request error:nil];
}
As you can see, I've deleted the merge in the update status. So probably, it cause merge conflict in the reset status. So, I guess I will have to fix the merge progress. So I'll ask to people here if you have any idea about this.