0
votes

I have a problem with Core Data and NSMutableArray. Reading this document: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdPerformance.html#//apple_ref/doc/uid/TP40003468-SW2 in the chapter "Faulting Behavior" I read: Since isEqual and hash do not cause a fault to fire, managed objects can typically be placed in collections without firing a fault.

Ok, for this reason, I understand that I can: - fetch the managedObjectContext - put all managed object into an array (the objects contains image data)

without firing a fault and waste memory (until the object is accessed for the first time), correct?

But, for some reason, Core Data is firing a fault when I try to put the result in an NSMutableArray

NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:request error:&error]; //this line does'n fire a fault
self.cache = [NSMutableArray arrayWithArray:fetchResults]; //this line fires a fault

self.cache is simply a NSMutableArray. After the last line of code, I see the memory usage growing through instruments (I have 50MB of images in the DB, and the memory goes immediately from 2-3Mb to 52-53MB.

Any suggestion? Thanks

1
Just checking, you haven't overridden isEqual: or hash?Carl Veazey
How do you know if/when faults are firing or not? Are you logging SQL statements? Using Instruments? Guessing?Jody Hagins
@Carl: no, i haven't overriden that methods.LombaX
@Jody, I'm using instruments. I see that the memory occupation increases after the last instruction. My managed object has simply 2 vars: one string and one image. All images in the db are (by now) about 50MB. I see that after the last instruction the memory occupation increases to 50MB. I expect to see this increment only after an access to the images (which causes the fault to fire)...or not?LombaX

1 Answers

0
votes

Ok, It was my mistake looking only to the Instruments memory occupation to determine if the fault was firing.

Core Data documentation says: If you need to determine whether an object is a fault, you can send it an isFault message without firing the fault. If isFault returns NO, then the data must be in memory. However, if isFault returns YES, it does not imply that the data is not in memory. The data may be in memory, or it may not, depending on many factors influencing caching.

I added this code after the "incriminate" lines:

for (ImageCache *cache in self.cache) {
    NSLog(@"Is fault? %i", [cache isFault]);
}

The result was 1 for all the objects.

Then I modified the for loop:

for (ImageCache *cache in self.cache) {
    NSLog(@"Is fault? %i", [cache isFault]);
    UIImageView *imageView = [[UIImageView alloc]initWithImage:cache.image];
    NSLog(@"Is fault? %i", [cache isFault]);
}

The result was 1 for the first NSLog, and 0 for the second NSLog of each object (the fault fired after the access to the image)

As the documentations says, it seems that Core Data is correctly faulting my objects, the memory occupation is due to Core Data caches. Mea culpa :-) (although I'm still curious to see how it behaves in real low memory situations. I expect this cache to flush...trying to send a memory warning has no effects on the memory size) Thanks