My core data store contains 51 Entry
entities which have a message
attribute reading "Test". Doing an NSFetchRequest for this confirms that they're all there.
I have another part of my method however, which will be used for memory intensive purposes, dealing with large chunks of NSData, and so I need to call [oldContext reset];
quite often.
I have a memory intensive method which accesses a lot of NSData from my MOC. As such, it regularly calls [oldContext reset];
. Without this line, it runs out of memory.
I've discovered that by using this though, it's not returning the correct results. To test this, I commented out the data intensive code, leaving me with code which returned the message
attribute, 51 of which are set to "Test" (confirmed by a separate NSFetchRequest).
Using [oldContext reset];
however, it only returns 6 results with the message set to "Test". This is the code I'm using:
NSFetchRequest *oldFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *oldEntryEntity = [NSEntityDescription entityForName:@"Entry"
inManagedObjectContext:oldContext];
[oldFetchRequest setEntity:oldEntryEntity];
[oldFetchRequest setFetchBatchSize:10];
[oldFetchRequest setIncludesPropertyValues:NO];
NSArray *entrys = [oldContext executeFetchRequest:oldFetchRequest error:&error];
int totalEntries = [oldContext countForFetchRequest:oldFetchRequest error:nil];
int i = 0;
while (i < totalEntries) {
@autoreleasepool {
Entry *entry = [entrys objectAtIndex:i];
NSLog(@"message 1: %@", [entry valueForKey:@"message"]);
[oldContext reset];
i++;
}
}
Any thoughts as to why it's not giving the 51 "Test" results it should do?
The above code executes a fetch request on the MOC
oldContext
. As a result, theentrys
array will contain managed objects for each object in the database that matches the request. In addition, as a result of setting the batch size, the fetch will fault your batch size of objects.As an experiment to assure yourself of what is happening, add these log statements...
Do you see what is in that array? Does it make sense now?
Let's look at the rest of the code.
I would suggest a different method. Calling
reset
is not designed for contexts in which you will retain objects.There are several alternatives. You could create a child context, do your scratch work in there, and then release the context. It will release all memory it used.
You could selectively use
which will turn an object back into a fault if
flag
isNO
, freeing its memory. Note, there are also some inherent dangers with this as well, especially if you have managed relationships.There are a few other options, but without having knowledge of what your ultimate goal is... it's kinda hard to tell what would be most beneficial.
I highly suggest you read all the documentation associated with these calls. In fact, while Core Data is very sophisticated, it does have some "brittle" inter-workings that you should know about if you do anything non-trivial.
I highly recommend reading all the Core Data documentation. It addresses all the issues you have been having with your project.