How can I guarantee unique entries in a Core Data store in a shared app container used by both the host app and an extension?

后端 未结 2 1543
故里飘歌
故里飘歌 2021-01-30 12:04

To ask my question effectively, let\'s first consider the exact scenario I\'m facing:

General Setup

  • A host iOS 8 app.
  • One or more
相关标签:
2条回答
  • 2021-01-30 12:17

    Is there a known approach to this rather novel problem introduced by iOS 8 extensions?

    Yes, it's the same approach that applies when using iCloud with Core Data: let the duplicates happen, but then go and clean them up. Both situations run the risk of creating duplicate entries, and there's no completely reliable way to prevent them. Since you have a uniqueID key, you're in good shape as far as this is concerned.

    It would be a lot easier, as Dave DeLong notes, to avoid the problem in the first place. If that's impossible, you can deal with it, with some extra work.

    Finding duplicates would be something like:

    NSError *error = nil;
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
    [moc setPersistentStoreCoordinator:self.persistentStoreCoordinator];
    
    NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"MyEntityName"];
    [fr setIncludesPendingChanges:NO];
    
    NSExpression *countExpr = [NSExpression expressionWithFormat:@"count:(uniqueID)"];
    NSExpressionDescription *countExprDesc = [[NSExpressionDescription alloc] init];
    [countExprDesc setName:@"count"];
    [countExprDesc setExpression:countExpr];
    [countExprDesc setExpressionResultType:NSInteger64AttributeType];
    
    NSAttributeDescription *uniqueIDAttr = [[[[[_psc managedObjectModel] entitiesByName] objectForKey:@"MyEntityName"] propertiesByName] objectForKey:@"uniqueID"];
    [fr setPropertiesToFetch:[NSArray arrayWithObjects:uniqueIDAttr, countExprDesc, nil]];
    [fr setPropertiesToGroupBy:[NSArray arrayWithObject:uniqueIDAttr]];
    
    [fr setResultType:NSDictionaryResultType];
    
    NSArray *countDictionaries = [moc executeFetchRequest:fr error:&error];
    

    This is pretty much the Core Data equivalent of something like this in SQL:

    SELECT uniqueID, COUNT(uniqueID) FROM MyEntityName GROUP BY uniqueID;
    

    You get an array of dictionaries, each of which contains a uniqueID and a count of the number of times that value is used. Run through the dictionary and deal with duplicates appropriately.

    I described this in more detail in a blog post. There's also a sample project from Apple that demonstrates the process, called SharedCoreData, but I believe it's only available as part of the WWDC 2012 sample code bundle. It was also described in session 227 at that conference.

    0 讨论(0)
  • 2021-01-30 12:19

    It seems like the simplest approach to this would be to simply avoid the multiple writers in the first place. Why not just drive your extensions entirely off cached data, and then only update your data store from your primary iOS app?

    0 讨论(0)
提交回复
热议问题