views:

38

answers:

2

Hi guys, in my app I need loop through all my entities in Core Data and I'm using NSFetchedresultcontroller.

I'm doing it like this at the moment:

NSArray *tempArray = [[NSArray alloc] initWithArray:self.fetchedResultsController.fetchedObjects];

for (MyClass *item in tempArray)
{
    // do something
}

[tempArray release]; tempArray = nil;

Is there any better way to do it without creating the tempArray?

Thanks a lot

A: 

Sorry, I think the answer is obvious:

        for (MyClass *item in self.fetchedResultsController.fetchedObjects)
        {
            //do something
        }

Is it a good way to do it memory-wise?

Burjua
+1  A: 

Depends on what you want to do. If you are just changing a value then yes, there is an easier way:

[[[self fetchedResultsController] fetchedObjects] setValue:someValue forKey:@"someKey"]

Which would loop through all of the objects setting the value. This is a standard KVC operation. Note that this will expand memory as each entity will get realized during the mutation.

If you need to do something far more involved with each entity or you are running into a memory issue then things get a bit more complicated. NOTE: Do not worry about memory until the optimization stage of coding. Pre-optimization of memory issues, especially with Core Data, is a waste of your time.

The concept is that you will loop over each entity and change it as needed. In addition, at a certain point you should save the context, reset it and then drain a local autorelease pool. This will reduce your memory usage as you will push the objects you just manipulated back out of memory before you pull the next batch in. For example:

NSManagedObjectContext *moc = ...;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSInteger drainCounter = 0;
for (id object in [[self fetchedResultsController] fetchedObjects]) {
  //Do your magic here
  ++drainCounter;
  if (drainCounter = 100) {
    BOOL success = [moc save:&error];
    NSError *error = nil;
    NSAssert2(!success && error, @"Error saving moc: %@\n%@", [error localizedDescription], [error userInfo]);
    [moc reset];
    [pool drain], pool = nil;
    pool = [[NSAutoreleasePool alloc] init];
    drainCounter = 0;
  }
}

BOOL success = [moc save:&error];
NSError *error = nil;
NSAssert2(!success && error, @"Error saving moc: %@\n%@", [error localizedDescription], [error userInfo]);
[pool drain], pool = nil;

This will keep memory usage down but it is expensive!! You are hitting disk after every 100 objects. This should only be used after you have confirmed that memory is an issue.

Marcus S. Zarra