5

My question: Is there anything bad about reusing an NSFetchRequest for several different fetches with Core Data?

Example code:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *logEntity = [NSEntityDescription entityForName:@"LogEntry" inManagedObjectContext:context];
[request setEntity:logEntity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dateTimeAction" ascending:NO]; // ascending NO = start with latest date
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status == %@",@"op tijd"];
[request setPredicate:predicate];
[request setFetchLimit:50];

NSError *error = nil;
NSInteger onTimeCount = [context countForFetchRequest:request error:&error];

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"status == %@",@"uitgesteld"];
[request setPredicate:predicate1];
[request setFetchLimit:50];

NSInteger postponedCount = [context countForFetchRequest:request error:&error];

NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"status == %@",@"gemist"];
[request setPredicate:predicate2];
[request setFetchLimit:50];

NSInteger missedCount = [context countForFetchRequest:request error:&error];
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Pieter
  • 1,751
  • 3
  • 30
  • 65

3 Answers3

5

It's not a problem, but in the example given it's not gaining you much (just some code brevity.) The most expensive part of creating a fetch request is parsing the predicate format string.

If the code you've given is called frequently, and you're looking to speed it up, here are some ideas to try:

  • Create all the predicates and fetch request just once: maybe in a dispatch_once() block and storing them statically; or in the constructor and stored in object fields
  • Don't specify sort descriptors, since order doesn't matter if you only care about the count
  • If the actual predicates will be more complex or flexible than shown, create one general template predicate with substitution variables, and use predicateWithSubstitutionVariables: to generate specified copies.
  • For even more code brevity, define that template in the object model using the model editor, and use fetchRequestFromTemplateWithName:substitutionVariables: to create fetch requests.

I can gin up some sample code if you like.

rgeorge
  • 7,385
  • 2
  • 31
  • 41
  • The sort descriptor is needed to get the latest 50 elements in combination with [request setFetchLimit:50];. I guess I could set the fetchLimit once for all requests. – Pieter May 20 '12 at 19:16
  • Ah. Then, If you're reusing the FR to fetch the actual log entries later, as well as just counting them as shown, I'd suggest setting the sort descriptors only during the object fetch and back to nil during the count fetch. If there are more than 50, the count fetch will return 50 no matter "which ones" it's counting. – rgeorge May 20 '12 at 21:21
1

I don't think that it's a problem, because the NSFetchedRequest is just a search criteria descriptor, moreover you can have multiple predicates on your fetched request like this:

NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:NSArray_of_predicates];
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
graver
  • 15,183
  • 4
  • 46
  • 62
1

It's OK if you reuse them with the same store, or perhaps different stores with the same model. I ran into crashes (e.g. in NSKnownKeysDictionary1) when using the same fetch request to query multiple stores that had different models. It seemed to make sense to reuse the request since I was fetching the same entity, just from two different places. The entity name and predicate were the same. You would think this would be OK since the fetch request takes an entity name rather than an entity description; the latter would be a different (but equivalent) object for the same entity in different stores/models. However, it looks like the fetch request caches the entity description and doesn't check that it's still valid for the current context that it's being executed against.

You can, however, reuse the same predicate in multiple fetch requests without problems.

Michael Tsai
  • 1,945
  • 17
  • 41