0

I have the following method which is called within a FOR Loop and is called several times, each time iterating through an NSDictionary object to create and set a note object :

- (BOOL)updateById:(NSString *)entityId
      withData:(NSDictionary *)dataDictionary {


DLog(@"Updating %@", [_entityClass description]);

if (_entityIdentifier == nil) {
    DLog(@"entityIdentifier has not been set");

}

NSManagedObjectContext *context = ContextForThread;

id note = [_entityClass findFirstByAttribute:_entityIdentifier
                                   withValue:entityId
                                   inContext:context]; //This is running slowly ?

[note setValuesFromDictionary:dataDictionary]; 

BOOL changes = YES;
if ([note changedValues].count == 0) {
    changes = NO;
    DLog(@"Has NOT changed - Dont save");
}
else {
    DLog(@"Has changed");

}

return changes;

}

I am trying to optimise this code and have noticed that the findFirstByAttribute method seems to be rather slow. Is there anyway I can optimise this method ?

4

2 回答 2

2

Fundamentally, the problem is that you're doing a lot of fetches, and lots of fetches mean lots of work. Your goal here should be to reduce the number of fetches, most likely by doing them all in one shot and then refactoring your code to use the results. For example, if the entityId values are known in advance:

  1. Fetch all instances using the known entityId values. I don't know if MR has a shortcut for this. Using Core Data directly, you'd something like the following with the fetch. The results of the fetch would be all instances where the value of _entityIdentifier is in the entityIds array:

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K in %@", _entityIdentifier, entityIds);
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey: _entityIdentifier ascending:YES];
    
  2. Refactor your method above so that you pass in both a managed object and the dictionary of values you want to assign to that object.

There are other ways to approach this, but one way or another you should fetch multiple objects at once instead of doing a separate fetch for each one.

于 2013-10-01T20:38:50.897 回答
1

Setting the attribute to be indexed should help a bit. Other than that consider doing batch updates if you call this method very often. You could use MR_findAllWithPredicate to make a single DB query and the update values for each retrieved object.

于 2013-10-01T19:11:20.250 回答