I have an app that allows users to save favorites. I am using Core Data to store the favorites as managed objects. I have written some code to prevent the possibility of storing
If you're dealing with multiple records, iterating over a count fetch or retrieving actual objects is VERY costly on the CPU. In my case, I did one fetch for all matching records, but asked for a dictionary of just the string of the UUID back. Saves a lot of CPU overhead.
For example, I have a uUID property on every record in core data. I have a corresponding UUID listed as @"UUID" in CloudKit.
//1. Create a request for the entity type, returning an array of dictionaries
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"someEntityName"];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch: @[@"uUID"]];
//2. Create an array of UUID strings of the downloaded objects
NSMutableArray *UUIDstrings = [NSMutableArray new];
for (CKRecord *record in ckRecords) {
[UUIDstrings addObject:record[@"UUID"]];
}
//3. Create a predicate to find any Core Data objects with the same UUID
[request setPredicate:[NSPredicate predicateWithFormat:@"uUID in %@", UUIDstrings]];
//4. If there are results from the fetch, do a log and you'll see it's a dictionary.
NSArray *deck = [self.MOC executeFetchRequest:request error:nil];
NSLog(@"Logging the result of index 0. Should be a dictionary %@", deck.count > 0 ? [deck objectAtIndex:0] : @"No results");
//5. Then either do an embedded fast enumeration (for xx in xx){for xx in xx} to find a match like
if ([(NSString *)record[@"UUID"] isEqualToString:[dict valueForKey:@"uUID"]])
{do something}
//...Or 6. Use a more linear approach with NSSet
//Harvest the core data strings
NSMutableArray *coreDataStrings = [NSMutableArray new];
for (NSDictionary *dict in deck) {
[coreDataStrings addObject:[dict objectForKey:@"uUID"]];
}
//Create a set of your downloaded objects
NSSet *arraySet = [NSSet setWithArray:ckRecords];
//Then use a predicate search - a NOT version of above
NSArray *final = [[arraySet filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"NOT(UUID in %@)", coreDataStrings]]allObjects];
The console log of the dictionary will look something like this. Just the smallest amount of info required to match:
dictionary {
uUID = "AFACB8CE-B29E-4A03-9284-4BD5F5464";
}
More here at the developer site on finding unique values.