web-dev-qa-db-ja.com

オブジェクトがコアデータに存在するかどうかを確認する最速の方法は?

オブジェクトがCore Dataに保持されているかどうかを確認したい。たとえば、Core DataにFriendsがあり、firstNameでそれらを識別します。コアデータをクエリして、「George」が既知かどうかを確認できます。結果セットの配列に0個以上のオブジェクトが含まれている場合、Georgeがいることがわかります。しかし、Core Dataはすべてをメモリにロードします。実際、ジョージが保存されているかどうかを知りたいだけです。

最も効率的な方法はどうすればよいですか?

53

コアデータリクエストを設定し、実際にクエリを発行する代わりに、以下を実行します。

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;
96
Massimo Cafaro

はい、間違いなくより良い方法があります。フェッチリクエストを通常どおりセットアップしますが、実際に実行する代わりに、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;

}
25
shaikh

目的がオブジェクトの存在を確認することである場合、解決策はフレンドモデルにこのメソッドを実装することです。

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

Core Data Documentation によると、オブジェクトが存在するかどうかを確認するためにフェッチを続けるべきではありません。

個別の入力値のセットについて、既存のオブジェクト(ストアに既に保存されているオブジェクト)を見つける必要がある場合が多くあります。簡単な解決策は、ループを作成し、値ごとにフェッチを実行して、一致する永続オブジェクトなどがあるかどうかを判断することです。このパターンはうまくスケーリングしません。このパターンでアプリケーションをプロファイリングすると、通常、フェッチはループ内でより高価な操作の1つであることがわかります(アイテムのコレクションを反復処理する場合に比べて)。さらに悪いことに、このパターンはO(n)問題をO(n ^ 2)問題に変えます。

3月16日編集
私はデータベースの専門家ではありませんが、人々はより効率的なソリューションを求めているため、このセットを検討してください。

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

[mango, Apple, grape]はこのセットの一部です。

ドキュメントでは、[mango、Apple、grape]を反復処理せず、データベースを照会して各アイテムを順番に検索するように指示しています。これは遅いためです。

この解決策を検討してください。

サーバー側でセットをハッシュします。

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

その後、サーバーに何か変更があったかどうかを尋ねることにより、コアデータを完全にバイパスできます。セットが異なる場合は、管理対象オブジェクトコンテキストでオブジェクトをダンプし、一括保存を実行できます。

各オブジェクトが順番にセットの一部であるかどうかを確認したい場合は、「フルーツ付きスキン」などのインデックス付き特性に基づいてフェッチを実行できます。

6
Jon

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
    }
}
0
JhonnyTawk