Reputation: 345
In my app I am using core data to store information. When the app is initially launched this block of code is called to fetch the data:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName: @"Customer" inManagedObjectContext: managedObjectContext];
request.entity = entity;
NSError *error = nil;
Array = [[managedObjectContext executeFetchRequest: request error: &error] mutableCopy];
NSArray * reversedArray = [[Array reverseObjectEnumerator] allObjects];
[Array release];
Array = nil;
[request release];
[error release];
So everything works correctly but there is a very large amount of memory allocated that isn't getting released and I can't seem to figure it out. You can see by the screenshots below. Any help would be great.
EDIT
I originally accepted the answer below but it doesn't seem to get rid of the issue 100 percent. CFData (store) is still allocating a lot of memory which isn't getting freed. This eventually is causing a crash on an iPad 2 which I didn't experience when I accepted the answer below because I was only testing on an iPad 4. I hope this clears everything up.
EDIT 2
So I've been doing more testing and debugging and it seems that the more entries that are added to core data the larger the CFData (store) is getting. Currently there are only 10 separate entries in the database and the allocation from fetching them is more then 25mb when the app is opened. The main entity "Customer" has multiple relationships with other bigger entities. So when I preform the fetch of "Customer", every entity that it has a relationship with is being fetched which is causing the huge memory allocation. Is there a way to get around this issue?
I'm guessing there has to be a better way to set up how the entries are added and how they are fetched.
Here is the code for how an entry is created:
- (void) addItem
{
// Insert a new record in the database
Customer * customerItem = [NSEntityDescription insertNewObjectForEntityForName: @"Customer" inManagedObjectContext: managedObjectContext];
System * system = [NSEntityDescription insertNewObjectForEntityForName: @"System" inManagedObjectContext: managedObjectContext];
Form1 * form1 = [NSEntityDescription insertNewObjectForEntityForName: @"Form1" inManagedObjectContext: managedObjectContext];
Form2 * form2 = [NSEntityDescription insertNewObjectForEntityForName: @"Form2" inManagedObjectContext: managedObjectContext];
Form3 * form3 = [NSEntityDescription insertNewObjectForEntityForName: @"Form3" inManagedObjectContext: managedObjectContext];
Form4 * form4 = [NSEntityDescription insertNewObjectForEntityForName: @"Form4" inManagedObjectContext: managedObjectContext];
Form6 * form6 = [NSEntityDescription insertNewObjectForEntityForName: @"Form6" inManagedObjectContext: managedObjectContext];
Form7 * form7 = [NSEntityDescription insertNewObjectForEntityForName: @"Form7" inManagedObjectContext: managedObjectContext];
Form8 * form8 = [NSEntityDescription insertNewObjectForEntityForName: @"Form8" inManagedObjectContext: managedObjectContext];
Form9 * form9 = [NSEntityDescription insertNewObjectForEntityForName: @"Form9" inManagedObjectContext: managedObjectContext];
Form10 * form10 = [NSEntityDescription insertNewObjectForEntityForName: @"Form10" inManagedObjectContext: managedObjectContext];
Form11 * form11 = [NSEntityDescription insertNewObjectForEntityForName: @"Form11" inManagedObjectContext: managedObjectContext];
customerItem.system = system;
customerItem.form1 = form1;
customerItem.form2 = form2;
customerItem.form3 = form3;
customerItem.form4 = form4;
customerItem.form6 = form6;
customerItem.form7 = form7;
customerItem.form8 = form8;
customerItem.form9 = form9;
customerItem.form10 = form10;
customerItem.form11 = form11;
// Insert a new item in the table's data source
[customerArray insertObject: customerItem atIndex: 0];
[managedObjectContext save: &error];
// Insert a new row in the table
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: 0 inSection: 0];
[table insertRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
Upvotes: 2
Views: 932
Reputation: 29886
Core Data is going to have some amount of long-lived memory that it needs to in order to perform its function. That said, you can be extra sure you've minimized memory use here by wrapping this code in an @autorelease
pool, like this:
@autoreleasepool {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName: @"Customer" inManagedObjectContext: managedObjectContext];
request.entity = entity;
NSError *error = nil;
Array = [[managedObjectContext executeFetchRequest: request error: &error] mutableCopy];
NSArray * reversedArray = [[[Array reverseObjectEnumerator] allObjects] retain];
[Array release];
Array = nil;
[request release];
[error release];
}
[reversedArray autorelease];
Even though you have been careful to release all the objects that you create, the autorelease pattern is used extensively throughout the system frameworks.
Note that with the addition of this @autoreleasepool
, you need to retain reversedArray
in order for it to last across the exiting of the pool's scope. I added [reversedArray autorelease]
afterward so the code is semantically identical to the code you posted (except for the releasing of any autoreleased objects created by the execution of the fetch request.)
Upvotes: 1