ioscore-datacloudkit

The Impact of propertiesToFetch on Core Data Performance: Surprising Results


I am facing the following issue with Core Data + CloudKit data storage. Can anyone help me understand the reason behind it?

Let's assume I have a Person entity with several attributes: name, age, gender, and photo. The photo attribute stores UIImage content, and I have set its Type to "Transformable." After saving a large number of Person objects, the performance of fetching the Person list becomes very slow, taking around 5 seconds for each query. I suspect that directly saving UIImage into Core Data is causing the slow performance.

To address this issue, I have set propertiesToFetch to @[@"name", @"age", @"gender"] and the resultType to NSManagedObjectResultType. The code looks like this:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Person"];
fetchRequest.propertiesToFetch = @[@"name", @"age", @"gender"];
fetchRequest.resultType = NSManagedObjectResultType;

NSError *error = nil;
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
if (results) {
    for (NSManagedObject *object in results) {
        NSString *name = [object valueForKey:@"name"];
        NSNumber *age = [object valueForKey:@"age"];
        NSString *gender = [object valueForKey:@"gender"];
        UIImage *photo = [object valueForKey:@"photo"]; // Why is photo not nil?
    }
} else {
    NSLog(@"Error fetching data: %@", error);
}

After applying the above configuration, the query becomes significantly faster with almost no delay. I currently have two questions:

Why is the photo attribute still available even though it was not added to propertiesToFetch? Shouldn't it be nil? Since the photo attribute can still be queried successfully, why does the query speed improve?

I would like to understand the reasons behind these observations. Thank you for your help.

I read the official documentation and tried looking it up online and couldn't find the relevant answer


Solution

  • propertiesToFetch determines which attributes are fetched (for all the objects) when the fetch request is executed. You can still access the property later, but then it will fetched at that time, per object. This will be slower if you do it for all the objects, but it’s faster than pre-fetching for all of them if you only need a few.