我有一个允许用户保存收藏夹的应用。我使用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;
}
我想知道Core Data是否能够检查添加的对象是否重复。是否有可以处理重复检查的谓词?谢谢!
答案 0 :(得分:18)
CoreData本身并不是唯一的。它没有两个条目相同的概念。
要启用此类行为,您必须自行执行此操作,方法是执行“在插入前搜索”,即“在创建之前获取”。
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);
答案 1 :(得分:4)
我想知道Core Data是否能够检查添加的对象是否重复。
不,核心数据并不关心这一点。
是否有可以处理重复检查的谓词?
由于您的对象具有您控制的唯一ID,因此请使用该ID对现有收藏夹进行提取。像
这样的东西NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Favorite"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"stationIdentifier == %@", stID];
[fetch setPredicate:predicate];
如果您收到任何结果,则表示已存在具有该ID的收藏夹。并且,如果您想要更改它,您可以参考该收藏夹。
您目前的方法很好,如果只有少数收藏,可能会更快。进行抓取会更好地扩展到许多收藏夹。
答案 2 :(得分:4)
Swift 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
}
答案 3 :(得分:3)
只是自iOS 9.0以来的更新,您可以使用模型中的“唯一约束”轻松完成。但请注意,如果您的商店已包含重复的核心数据,则会在应用程序发布时自动迁移失败。
请参见此处 - core data unique constraints
答案 4 :(得分:1)
如果您正在处理多个记录,则迭代计数提取或检索实际对象在CPU上非常昂贵。在我的例子中,我对所有匹配的记录进行了一次提取,但是要求提供一个仅包含UUID字符串的字典。节省了大量的CPU开销。
例如,我在核心数据的每条记录上都有一个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];
字典的控制台日志看起来像这样。只需要匹配的最小信息量:
dictionary {
uUID = "AFACB8CE-B29E-4A03-9284-4BD5F5464";
}
答案 5 :(得分:0)
http://dorianroy.com/blog/2015/09/how-to-implement-unique-constraints-in-core-data-with-ios-9/
查看链接。它可从ios9获得。您可以在约束中设置键以停止重复。博客更详细。
希望它能帮助别人:)
答案 6 :(得分:0)
从@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
}