1

I am attempting to get the a list of unique values for a property on all of my objects (similar to [array valueForKeyPath:@"@distinctUnionOfObjects.key"]. From what I can tell, I should be able to accomplish this by creating an NSFetchRequest with resultType set to NSDictionaryResultType, specifying the propertiesToFetch and setting returnsDistinctResults to YES. Doing this does not seem to work.

I have created an entity called Person with the three attributes firstName, lastName and age. Here is the code I am trying to test this with:

NSManagedObjectModel *objectModel = [NSManagedObjectModel mergedModelFromBundles:nil];

NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:objectModel];
[coordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:nil];

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = coordinator;

[context performBlockAndWait:^{

    NSArray *lastNames = @[@"Smith",@"Johnson"];
    NSArray *firstNames = @[@"John", @"Susan"];

    for (NSString *lastName in lastNames) {
        for (NSString *firstName in firstNames) {
            Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
            person.firstName = firstName;
            person.lastName = lastName;
            person.age = @(18);
        }
    }

}];

[context save:nil];

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
fetchRequest.resultType = NSDictionaryResultType;
fetchRequest.propertiesToFetch = @[@"age"];
fetchRequest.returnsDistinctResults = YES;

NSArray *results = [context executeFetchRequest:fetchRequest error:nil];
NSLog(@"%@",results.description);

When I run this, this is the log I get:

2017-10-12 16:17:54.723 TestCoreData[10650:879197] (
        {
        age = 18;
    },
        {
        age = 18;
    },
        {
        age = 18;
    },
        {
        age = 18;
    }
)

Changing propertiesToFetch to @[@"lastName"] gives similar results:

2017-10-12 16:32:45.143 TestCoreData[10800:929908] (
        {
        lastName = Smith;
    },
        {
        lastName = Johnson;
    },
        {
        lastName = Johnson;
    },
        {
        lastName = Smith;
    }
)

My expectation would be that these would only return a single entry for age and two for lastName.

Am I misunderstanding the use of returnsDistinctResults or using it incorrectly?

Mean Dinosaur
  • 376
  • 1
  • 12
  • I just wonder whether it's a result of using the in memory store. Have you tried with a SQL store type? – pbasdf Oct 12 '17 at 21:07
  • @pbasdf yeah I was thinking the same thing after I posted this and tried it, and that seemed to be the problem. Thanks for the input. – Mean Dinosaur Oct 12 '17 at 21:29

1 Answers1

3

So it turns out this is occurring because I am using an in memory store. If I instead back this with an SQLite store, it works as expected, giving these results:

2017-10-12 17:21:48.546 TestCoreData[11767:1035544] (
        {
        age = 18;
    }
)

and

2017-10-12 17:23:52.632 TestCoreData[11803:1044179] (
        {
        lastName = Johnson;
    },
        {
        lastName = Smith;
    }
)

My guess is that the distinct functionality is something that occurs in the query statement and is not not present for fetches against in memory stores.

Mean Dinosaur
  • 376
  • 1
  • 12
  • I'm facing the same problem of multiples being returned even using `.returnDistinctResults = true` but I can't see if I have the same cause you had but I think not as I load data from CoreData persistent container. Could you please have a look at my code in question https://stackoverflow.com/questions/56168119/removing-duplicate-objects-from-fetch-based-on-object-parameter-swift to see if you spot the problem? I tried running the app on physical iPad but with same results. Many thanks – Vincenzo May 17 '19 at 08:43