Reputation: 16051
I've been working on this problem for weeks now, I just can't seem to solve it. I'm iterating through every entity in my database, to perform an action. I was using an NSFetchRequest for a while, but despite my attempts to stop it doing so, it kept increasing memory usage with every iteration, apparently not getting any memory back after each iteration. Now I'm using NSFetchedResultsController for the same task.
This is the code I have:
The NSFetchedResultsController:
- (NSFetchedResultsController *)updateController {
if (_updateController != nil) {
return _updateController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Entry" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"creationDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:10];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil
cacheName:nil];
self.updateController = theFetchedResultsController;
return _updateController;
}
And the code that it runs through:
NSLog(@"update controller: %@", [self updateController]);
if (![[self updateController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
int i = 0;
id sectionInfo = [[_updateController sections] objectAtIndex:0];
NSLog(@"count: %i", [sectionInfo numberOfObjects]);
NSManagedObject *entry;
while (i < [sectionInfo numberOfObjects]) {
@autoreleasepool {
entry = [_updateController.fetchedObjects objectAtIndex:i];
NSLog(@"entry: %@", [entry valueForKey:@"message"]);
NSLog(@"context 1: %@", [entry managedObjectContext]);
NSLog(@"context 2: %@", [[self updateController] managedObjectContext]);
[[entry managedObjectContext] refreshObject:entry mergeChanges:NO];
NSLog(@"i: %i", i);
i++;
}
}
Instruments shows this:
When I click on that period in the timeline it selects those entrys in the table that are showing. The period in the graph where its performing the task, data usage is increasing slightly as it goes on, from 1.14mb to 1.17mb. This isn't a lot at this stage, but adding in code which deals with larger data, such as NSData images, means that the app data usage rises until it eventually runs out of memory and crashes. The app's 1.0 version is already on the app store so simply not having NSData in my core data isn't an option.
Hope someone can help, thanks.
Upvotes: 2
Views: 237
Reputation: 10772
Have you actually tried adding a massive amount of objects to the data store, or are you extrapolating based on the data you've benchmarked so far? Core Data is usually very good at managing memory consumption.
Core data will turn your objects back into faults and release all of the associated memory when it detects that you're no longer using the object in question and your memory usage is getting high.
Using NSFetchRequest
's setFetchBatchSize:
will also help. It'll fetch objects from disk in small batches instead of all at once as you request more objects from the data store.
Upvotes: 1
Reputation: 106
There is an option you can enable on each object that is going to store a lot of data such as images. it stores any data over 1MB on the disk in a file; this should lower your memory usage.
Upvotes: 0