Monday, February 17, 2014

includesPropertyValues in Core Data

When ever from your iOS app if you are fetching values from a core data table very frequently just for some updated values or so, that time instead of creating n number of fetch request objects in memory (since core data manipulation happens in a memory context) and which causes unnecessarily memory pressure a major drawback in any apps performance. So as to handle these kind of situations optimally we need to make use of some of the basic properties provided from core data framework.

So here comes a very really decent and required API property of core data called “ includesPropertyValues

What is an includesPropertyValues?
You can set includesPropertyValues to NO to reduce memory overhead by avoiding creation of objects to represent the property values. 

By default includesPropertyValues is YES, Normally Core Data fetches the object Id & property data for the matching records, fills the row cache with the information, and returns managed object as faults. 
These faults are managed objects, but all of their property data still resides in the row cache until the fault is fired. When the fault is fired, Core Data retrieves the data from the row cache—there is no need to go back to the database.

If includesPropertyValues is NO, then Core Data fetches only the object ID information for the matching records—it does not populate the row cache. Core Data still returns managed objects since it only needs managed object IDs to create faults. However, if you subsequently fire the fault, Core Data looks in the (empty) row cache, doesn't find any data, and then goes back to the store a second time for the data.

When to use?
For example consider you are downloading some huge set of data(say, a finite number of images) from a remote server through a web service call and saving it in local persistence core data, and you want to show a progress bar showing the progress of downloaded data.
Say my table name is “ImageTabel” and their is a integer column called “downloadStatus” just to track the number of images downloaded and saved in local core database.
Consider initially all values  of downloadStatus column will be 0 representing that no data is downloaded yet and once the data downloads respective column values for downloadStatus will be updated by 1.
In this kind of conditions if we simply make n number of fetch requests just to update the progress bar, we actually need just totalNumber of downloaded images by fetching ImageTabel, downloadStatus column where values == 1; but table may contain few more attributes, no need to load all property values continuously in to memory.

In such cases if you set includesPropertyValues to NO, this will reduce the memory overhead by fetching only object Id information and does not load row cache.

example code snippet:
    NSEntityDescription *itemEntity = [NSEntityDescription entityForName:@"ImageTabel" inManagedObjectContext:[self managedObjectContext]];
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    fetch.includesPropertyValues = NO; //to reduce memory overhead.
    [fetch setEntity:itemEntity];
    NSPredicate *p = [NSPredicate predicateWithFormat:@"downloadStatus == 1"];
    [fetch setPredicate:p];

    NSError *fetchError;
    int totalDownloadedCount;
    NSArray *fetchedArray = [[self managedObjectContext] executeFetchRequest:fetch error:&fetchError];
    totalDownloadedCount = [fetchedArray count];
    fetchedArray = nil;
    return totalDownloadedCount;

The above countOfDownloadedQuestions method you may be calling in a loop or from an asynchronous web service callback so as to update a progress bar.

Note: You need to use this property only if you are sure that either you will not need the actual property data or you already have the information in the row cache, otherwise you will incur multiple trips to the database.

For further information on this topic you can visit Apple's developer document in the following URL,

Hope this post was helpful, any comments or suggestions are appreciated & acceptable :)