xcode 处理核心数据中的重复条目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18262003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 03:42:35  来源:igfitidea点击:

Handling duplicate entries in Core Data

iosobjective-cxcodecore-data

提问by Pheepster

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 duplicates, but am wondering if there is a better way to do so. Each favorite object has an ID field that is unique. In the following code I am simply looping through and checking the ID field, and if the value already exists, setting a flag value to true, and breaking out of the loop.

我有一个允许用户保存收藏夹的应用程序。我正在使用 Core Data 将收藏夹存储为托管对象。我已经编写了一些代码来防止存储重复项的可能性,但我想知道是否有更好的方法来这样做。每个收藏对象都有一个唯一的 ID 字段。在下面的代码中,我只是简单地循环并检查 ID 字段,如果该值已存在,则将标志值设置为 true,然后退出循环。

-(BOOL)addFavorite{
    BOOL entityExists = NO;
    if(context){
        // does this favorite already exist?
        NSArray *allFaves = [AppDataAccess getAllFavorites];
        for(Favorite *f in allFaves){
            if([f.stationIdentifier isEqualToString:stID]){
                entityExists = YES;
                break;
            }
        }
        if(!entityExists){
            NSError *err = nil;
            Favorite *fave = [Favorite insertInManagedObjectContext:context];
            fave.stationRealName = riverGauge.name;
            fave.stationIdentifier = stID;
            fave.stationState = @"WV";
            if(![context save:&err]){
                NSLog(@"ERROR: Could not save context--%@", err);
            }
            return YES;            
        }
    return NO;
}

I was wondering if Core Data has the ability to check to see if an object being added is a duplicate. Is there a predicate that can handle checking for duplicates? Thanks!

我想知道 Core Data 是否有能力检查添加的对象是否重复。是否有可以处理检查重复项的谓词?谢谢!

回答by Daij-Djan

CoreData does no uniquing by itself. It has no notion of two entries being identical.

CoreData 本身没有唯一性。它没有两个条目相同的概念。

To enable such a behavior you have to implement it yourself by doing a 'search before insert' aka a 'fetch before create'.

要启用这种行为,您必须通过执行“插入前搜索”又名“创建前获取”来自己实现。

NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Favorite"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stationIdentifier == %@", stID];
[fetch setPredicate:predicate];
YourObject *obj = [ctx executeRequest:fetch];

if(!obj) {
    //not there so create it and save
    obj = [ctx insertNewManagedObjectForEntity:@"Favorite"]; //typed inline, dont know actual method
    obj.stationIdentifier = stID;
    [ctx save];
}

//use obj... e.g.
NSLog(@"%@", obj.stationIdentifier);

Remember this assumes single-threaded access

请记住,这假定单线程访问

回答by shannoga

Just an update since iOS 9.0 you can do it easily with "unique constraints" in the model. But pay attention if your store already contains duplicate core data will fail any auto migration when the app shipped.

只是自 iOS 9.0 以来的更新,您可以使用模型中的“唯一约束”轻松完成。但是请注意,如果您的商店已经包含重复的核心数据,那么在应用程序发布时,任何自动迁移都会失败。

See here for example - core data unique constraints

例如,请参见此处 -核心数据唯一约束

回答by Tom Harrington

I was wondering if Core Data has the ability to check to see if an object being added is a duplicate.

我想知道 Core Data 是否有能力检查添加的对象是否重复。

No, Core Data doesn't care about that.

不,Core Data 不关心这个。

Is there a predicate that can handle checking for duplicates?

是否有可以处理检查重复项的谓词?

Since your objects have unique IDs that you control, do a fetch for an existing favorite with that ID. Something like

由于您的对象具有由您控制的唯一 ID,因此请使用该 ID 获取现有收藏夹。就像是

NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Favorite"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stationIdentifier == %@", stID];
[fetch setPredicate:predicate];

If you get any results, you know that a favorite with that ID already exists. And, you have a reference to that favorite in case you want to change it.

如果您得到任何结果,您就知道已存在具有该 ID 的收藏夹。而且,如果您想更改它,您可以参考该收藏夹。

Your current approach is fine and probably faster if there are only a few favorites. Doing a fetch will scale better to lots of favorites.

如果只有几个收藏夹,您当前的方法很好,并且可能更快。执行 fetch 将更好地扩展到许多收藏夹。

回答by Vahid

Swift 3:

斯威夫特3

func isExist(id: Int) -> Bool {
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: myEntityName)
    fetchRequest.predicate = NSPredicate(format: "id = %d", argumentArray: id)

    let res = try! theContext.fetch(fetchRequest)
    return res.count > 0 ? true : false
}

回答by Tosin Onikute

Swift 4Curled from @Vahid answer

Swift 4Curled from @Vahid 答案

     func isEntityAttributeExist(id: Int, entityName: String) -> Bool {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let managedContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
        fetchRequest.predicate = NSPredicate(format: "id == %@", id)

        let res = try! managedContext.fetch(fetchRequest)
        return res.count > 0 ? true : false
      }

回答by Mike Critchley

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.

如果您正在处理多条记录,则在 CPU 上迭代计数获取或检索实际对象的成本非常高。就我而言,我对所有匹配的记录进行了一次提取,但要求提供一个仅包含 UUID 字符串的字典。节省大量CPU开销。

For example, I have a uUID property on every record in core data. I have a corresponding UUID listed as @"UUID" in CloudKit.

例如,我在核心数据中的每条记录上都有一个 uUID 属性。我在 CloudKit 中将相应的 UUID 列为 @"UUID"。

  //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 siteon finding unique values.

更多关于寻找独特价值的信息,请访问开发者网站

回答by Daniel

http://dorianroy.com/blog/2015/09/how-to-implement-unique-constraints-in-core-data-with-ios-9/

http://dorianroy.com/blog/2015/09/how-to-implement-unique-constraints-in-core-data-with-ios-9/

Check out the link. Its available from ios9. You can set keys in the constraints which will stop duplicates. The blog goes into greater detail.

查看链接。它可以从 ios9 获得。您可以在约束中设置键以阻止重复。该博客更详细地介绍了。

Hope it helps others :)

希望它可以帮助其他人:)