programing

객체가 Core Data에 존재하는지 여부를 확인하는 가장 빠른 방법은 무엇입니까?

copysource 2021. 1. 17. 11:52
반응형

객체가 Core Data에 존재하는지 여부를 확인하는 가장 빠른 방법은 무엇입니까?


객체가 Core Data에 유지되는지 확인하고 싶습니다. 예를 들어 핵심 데이터에 친구가 있고 firstName으로 식별합니다. 핵심 데이터를 쿼리하여 "George"가 알려져 있는지 확인할 수 있습니다. 결과 집합 배열에 0 개 이상의 개체가 포함 된 경우 George가 있다는 것을 알고 있습니다. 하지만 Core Data는 모든 것을 메모리에로드하고 저는 George가 저장되었는지 여부를 알고 싶습니다.

가장 효율적인 방법은 무엇입니까?


Core Data 요청을 설정하고 실제로 쿼리를 실행하는 대신 다음을 수행합니다.

NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request
                                                        error:&error];
if (!error) {
    return count;
} else {
  return 0;
}

실제로 메서드 countForFetchRequest:error:는 지정된 가져 오기 요청이 전달 된 경우 반환했을 개체 수를 반환합니다 executeFetchRequest:error:.


편집 : (정규식에 의해)

Josh Caswell이 올바르게 설명 했듯이 오류를 처리하는 올바른 방법은 다음 중 하나입니다.

if (count == NSNotFound) {
    NSLog(@"Error: %@", error);
    return 0;
}
return count;

또는 (오류 로깅없이) :

return (count != NSNotFound) ? count : 0;

예, 확실히 더 나은 방법이 있습니다. 평소와 같이 가져 오기 요청을 설정하지만 실제로 실행하는 대신 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;

}

목표가 객체가 존재하는지 확인하는 것이라면 해결책은 Friend Model에서이 메서드를 구현하는 것입니다.

-(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;
    }
}

Core Data Documentation 에 따르면 개체가 있는지 확인하기 위해 계속 가져 와서는 안됩니다.

There are many situations where you may need to find existing objects (objects already saved in a store) for a set of discrete input values. A simple solution is to create a loop, then for each value in turn execute a fetch to determine whether there is a matching persisted object and so on. This pattern does not scale well. If you profile your application with this pattern, you typically find the fetch to be one of the more expensive operations in the loop (compared to just iterating over a collection of items). Even worse, this pattern turns an O(n) problem into an O(n^2) problem.

Edit March 16:
I am not a db expert, but since people are asking for a more efficient solution, consider this set:

set1 = [apple, orange, banana, pineapple, lettuce]

We want to find out if [mango, apple, grape] is a part of this set.

The docs tell us not to iterate through [mango, apple, grape] and query the database looking for each item in turn because this is slow.

Consider this solution:

Hash the sets on the server side:

hash([mango, apple, grape]) = 234095dda321affe...

You can then bypass Core Data completely by asking the server if anything changed. If the sets are different, you can then dump the objects in a managed object context and do a bulk save.

If you were really looking to see if each object in turn was a part of the set, you could do a fetch based on an indexed characteristic, such as "fruit with skin".


Update to 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
    }
}

ReferenceURL : https://stackoverflow.com/questions/2252109/fastest-way-to-check-if-an-object-exists-in-core-data-or-not

반응형