Search code examples
iphoneobjective-ccore-datafault

Core Data. ExecuteFetchRequest with fault NSManagedObjects (not in RAM)


I need to execute fetch request. But when I do it I get not fault NSManagedObjects (each of the objects is about 5 Mb, that's why I get the memory warning). Apple provides faulting possibility for Core Data (when objects are not loaded in RAM). And I wanna my objects to use this possibility.

Here is my code

+ (NSMutableSet *)GetImagesWithPredicate:(NSPredicate *)predicate
{
    NSString *entityName = kEntityName;
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];;
    NSManagedObjectContext *context = appDelegate.managedObjectContext;
    NSEntityDescription *entityDesctiption = [NSEntityDescription 
                                              entityForName: entityName
                                              inManagedObjectContext:context];

    // find object
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesctiption];
    [request setPredicate:predicate];
    NSArray *objects = [context executeFetchRequest:request error:nil];
    [request release];
    if (objects == nil)
    {
        NSLog(@"there was an error");
        return nil;
    }
    NSMutableSet *set = [NSMutableSet setWithArray:objects];
    return set;
}

where predicate is (id < 500).

App crashes after

NSArray *objects = [context executeFetchRequest:request error:nil];

because all the data of objects appears in the RAM of iPhone.

It seems that default option returnsObjectsAsFaults = YES doesn't work.


Solution

  • The objects are probably being returned as faults; you can verify this with isFault. The issue is that Core Data automatically pre-fetches the property values for those objects and places them in the row cache (in memory). You can disable this behaviour by setting includesPropertyValues to NO on the NSFetchRequest object.

    See the includesPropertyValues documentation for details of all this and the performance implications.

    As an aside, you might not want to store lots of large objects in the database directly. You probably should look into using external storage if you're targeting iOS 5, or else using separate files yourself with their names/paths/ids in Core Data.