Самый быстрый способ проверить, существует ли объект в Core Data или нет?
Я хочу посмотреть, сохраняется ли объект в Core Data или нет. Например, у меня есть Друзья в базовых данных, и я идентифицирую их по первому имени. Я могу запросить основные данные, чтобы узнать, известен ли "Джордж". Если массив результирующего набора содержит больше нуля объектов, я знаю, что у него есть Джордж. Но Core Data загружает все это в память, и я просто хочу знать, сохранен ли Джордж или нет.
Как я могу сделать это наиболее эффективным способом?
Ответы
Ответ 1
Настройте запрос Core Data и вместо фактического выдачи запроса выполните следующие действия:
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;
Ответ 2
Да, определенно есть лучший метод. Настройте запрос на выборку, как обычно, но вместо того, чтобы выполнять его, просто попросите количество объектов, которые оно вернет, если оно было передано в executeFetchRequest: error:
Это можно сделать, используя
- (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;
}
Ответ 3
Если цель состоит в том, чтобы проверить, существует ли объект, решение заключается в реализации этого метода в вашей модели Friend:
-(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;
}
}
Ответ 4
Согласно Документация по основным данным, вы не должны продолжать выборку, чтобы увидеть, существуют ли объекты.
Существует множество ситуаций, когда вам может потребоваться найти существующие объекты (объекты, уже сохраненные в хранилище) для набора дискретных входных значений. Простое решение - создать цикл, затем для каждого значения, в свою очередь, выполните выборку, чтобы определить, существует ли соответствующий сохраняемый объект и т.д. Этот шаблон плохо масштабируется. Если вы профилируете свое приложение с помощью этого шаблона, вы, как правило, считаете, что выборка является одной из более дорогих операций в цикле (по сравнению с простое повторение набора элементов). Хуже того, этот шаблон превращает проблему O (n) в задачу O (n ^ 2).
Изменить 16 марта:
Я не специалист по db, но поскольку люди просят более эффективное решение, рассмотрите этот набор:
set1 = [apple, orange, banana, pineapple, lettuce]
Мы хотим узнать, является ли [mango, apple, grape]
частью этого множества.
Документы говорят нам не перебирать через [манго, яблоко, виноград] и запрашивать базу данных, которая ищет каждый элемент по очереди, потому что это медленно.
Рассмотрим это решение:
Сбросить настройки на стороне сервера:
hash([mango, apple, grape]) = 234095dda321affe...
Затем вы можете полностью обходить Core Data, спросив сервер, если что-то изменится.
Если наборы разные, вы можете сбрасывать объекты в контексте управляемого объекта и выполнять массовое сохранение.
Если вы действительно хотели посмотреть, будет ли каждый объект в свою очередь частью набора, вы можете сделать выборку на основе индексированной характеристики, такой как "фрукты с кожей".
Ответ 5
Обновление до 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
}
}