我想知道对象是否在Core Data中持久存在。例如,我在Core Data中有Friends,我通过firstName识别它们。我可以查询核心数据以查看“George”是否已知。如果结果集数组包含多个零对象,我知道George就在那里。但是核心数据将整个内容加载到内存中,我实际上只是想知道乔治是否存储。
我如何以最有效的方式做到这一点?
答案 0 :(得分:96)
设置核心数据请求,而不是实际发出查询,请执行以下操作:
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request
error:&error];
if (!error) {
return count;
} else {
return 0;
}
实际上,方法countForFetchRequest:error:
会返回给定获取请求传递给executeFetchRequest:error:
时返回的对象数。
修改: (由Regexident提供)
正如 Josh Caswell 正确评论,处理错误的正确方法是:
if (count == NSNotFound) {
NSLog(@"Error: %@", error);
return 0;
}
return count;
或者此(没有错误记录):
return (count != NSNotFound) ? count : 0;
答案 1 :(得分:25)
是的,绝对有更好的方法。像往常一样设置一个获取请求,但是,如果它已经传递给executeFetchRequest,只需询问它将返回的对象数量:错误:
这可以使用
完成- (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error:(NSError **)error;
这样的事情:
- (int) numberOfContacts{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSManagedObjectContext *managedObjectContext = yourManagedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Contacts" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
[request release];
if (!error){
return count;
}
else
return -1;
}
答案 2 :(得分:7)
如果目标是检查对象是否存在,解决方案是在您的朋友模型中实现此方法:
-(BOOL)exist
{
NSManagedObjectContext *managedObjectContext = yourManagedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Friends" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setFetchLimit:1];
[request setPredicate:[NSPredicate predicateWithFormat:@"firstName == %@", self.firstName]];
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
if (count)
{
return YES;
}
else
{
return NO;
}
}
答案 3 :(得分:6)
根据Core Data Documentation,您不应该继续查看对象是否存在。
在许多情况下,您可能需要查找一组离散输入值的现有对象(已存储在商店中的对象)。一个简单的解决方案是创建一个循环,然后为每个值依次执行一个fetch以确定是否存在匹配的持久化对象,依此类推。这种模式不能很好地扩展。如果使用此模式分析应用程序,通常会发现fetch是循环中较昂贵的操作之一(与仅迭代项目集合相比)。更糟糕的是,这种模式将O(n)问题转化为O(n ^ 2)问题。
编辑3月16日:
我不是数据库专家,但由于人们要求更有效的解决方案,请考虑这一组:
set1 = [apple, orange, banana, pineapple, lettuce]
我们想知道[mango, apple, grape]
是否属于此集合的一部分。
文档告诉我们不要遍历[芒果,苹果,葡萄]并查询数据库依次查找每个项目,因为这很慢。
考虑这个解决方案:
在服务器端散列集:
hash([mango, apple, grape]) = 234095dda321affe...
然后,您可以通过询问服务器是否有任何更改来完全绕过Core Data。 如果集合不同,则可以将对象转储到托管对象上下文中并进行批量保存。
如果您真的想要查看每个对象是否是该集合的一部分,您可以根据索引特征进行提取,例如“带有皮肤的水果”。
答案 4 :(得分:0)
更新为SWIFT 5:
func checkIfItemExist(id: Int, type: String) -> Bool {
let managedContext = CoreDataStack.sharedInstance.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "DetailsEntity")
fetchRequest.fetchLimit = 1
fetchRequest.predicate = NSPredicate(format: "id == %d" ,id)
fetchRequest.predicate = NSPredicate(format: "type == %@" ,type)
do {
let count = try managedContext.count(for: fetchRequest)
if count > 0 {
return true
}else {
return false
}
}catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return false
}
}