Подтвердить что ты не робот

Самый быстрый способ проверить, существует ли объект в Core Data или нет?

Я хочу посмотреть, сохраняется ли объект в Core Data или нет. Например, у меня есть Друзья в базовых данных, и я идентифицирую их по первому имени. Я могу запросить основные данные, чтобы узнать, известен ли "Джордж". Если массив результирующего набора содержит больше нуля объектов, я знаю, что у него есть Джордж. Но Core Data загружает все это в память, и я просто хочу знать, сохранен ли Джордж или нет.

Как я могу сделать это наиболее эффективным способом?

4b9b3361

Ответ 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
    }
}