Cocoa Core Dataでエンティティをカウントする効率的な方法


174

私はコアデータについて多くを読みましたが、Entity-Typeをカウントする効率的な方法は何ですか(SQLがSELECT count(1)...で実行できるように)。今、私はこのタスクをすべてで選択しNSFetchedResultsControllerNSArray!これは最善の方法ではないと確信しています...

回答:


303

NSFetchedResultsControllerを使用することがあなたの目標を達成するための最も効率的な方法であるかどうかはわかりません(しかし、そうかもしれません)。エンティティインスタンスの数を取得する明示的なコードは次のとおりです。

// assuming NSManagedObjectContext *moc

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:moc]];

[request setIncludesSubentities:NO]; //Omit subentities. Default is YES (i.e. include subentities)

NSError *err;
NSUInteger count = [moc countForFetchRequest:request error:&err];
if(count == NSNotFound) {
  //Handle error
}

[request release];

1
Leopard上であなたはcountForFetchRequestを使用したい:とないexecuteFetchRequest:
IlDan

そして、スキップして述語を設定します。述語なし:エンティティの説明に一致するすべてのオブジェクトを取得します
IlDan

4
ただ参考までに、特定のリクエストの結果がない場合はcount == 0、NSNotFound = NSIntegerMaxなので、結果がない場合は「// Handel error」は実行されません。
意図

タイプミスはありますか:setIncludesSubentities?ドキュメントでは、サンプルコードの大文字の「E」ではなく、「エンティティ」の小文字の「e」を示していると思います。
Mike

2
@LarsSchneider エラーの場合に返されるcountForFetchRequest:error:状態のドキュメントNSNotFound。一般に、NSErrorCocoa規約での処理では、errエラーが発生しない場合、の値は定義されていません(多くの場合危険です)。
Barry Wark、2011

61

明確にするために、エンティティを数えるのではなく、特定のエンティティのインスタンスを数えます。(文字通りエンティティを数えるには、管理対象オブジェクトモデルにエンティティの数を尋ねます。)

すべてのデータをフェッチせずに、特定のエンティティのすべてのインスタンスをカウントするには、を使用します-countForFetchRequest:

例えば:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity: [NSEntityDescription entityForName: entityName inManagedObjectContext: context]];

NSError *error = nil;
NSUInteger count = [context countForFetchRequest: request error: &error];

[request release];

return count;

32

迅速

コアデータのエンティティのインスタンスの総数を取得するのはかなり簡単です。

let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "MyEntity")
let count = context.countForFetchRequest(fetchRequest, error: nil)

400,000以上のオブジェクト数を使用してシミュレータでこれをテストしましたが、結果は(瞬間的ではありませんが)かなり高速でした。


23

それをさらに効率的にするために追加します...そして、それは単なるカウントなので、プロパティ値は実際には必要ありません。確かに、上記のコード例のように、サブエンティティも必要ありません。

したがって、コードは次のようになります。

int entityCount = 0;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"YourEntity" inManagedObjectContext:_managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
[fetchRequest setIncludesPropertyValues:NO];
[fetchRequest setIncludesSubentities:NO];
NSError *error = nil;
NSUInteger count = [_managedObjectContext countForFetchRequest: fetchRequest error: &error];
if(error == nil){
    entityCount = count;
}

それが役に立てば幸い。


10

オブジェクトをカウントする最も簡単で最も効率的な方法は、NSFetchRequest結果タイプをに設定しNSCountResultType、それをNSManagedObjectContext countForFetchRequest:error:メソッドで実行することです。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName];
fetchRequest.resultType = NSCountResultType;
NSError *fetchError = nil;
NSUInteger itemsCount = [managedObjectContext countForFetchRequest:fetchRequest error:&fetchError];
if (itemsCount == NSNotFound) {
    NSLog(@"Fetch error: %@", fetchError);
}

// use itemsCount

6

Swift 3がオブジェクトのカウントを取得するための簡単なユーティリティメソッドを作成しました。

static func fetchCountFor(entityName: String, predicate: NSPredicate, onMoc moc: NSManagedObjectContext) -> Int {

    var count: Int = 0

    moc.performAndWait {

        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
        fetchRequest.predicate = predicate
        fetchRequest.resultType = NSFetchRequestResultType.countResultType

        do {
            count = try moc.count(for: fetchRequest)
        } catch {
            //Assert or handle exception gracefully
        }

    }

    return count
}

3

Swift 3で

  static func getProductCount() -> Int {
    let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Product")
    let count = try! moc.count(for: fetchRequest)
    return count
}

1

それは本当にこれだけです:

let kBoat = try? yourContainer.viewContext.count(for: NSFetchRequest(entityName: "Boat"))

「ボート」は、データモデル画面のエンティティの名前です。

ここに画像の説明を入力してください

グローバルとはyourContainer

コアデータを使用するには、アプリのある時点で、一度だけ、

var yourContainer = NSPersistentContainer(name: "stuff")

ここで、「stuff」はデータモデルファイルの名前です。

ここに画像の説明を入力してください

あなたは単にこれのためのシングルトンを持っているでしょう、

import CoreData
public let core = Core.shared
public final class Core {
    static let shared = Core()
    var container: NSPersistentContainer!
    private init() {
        container = NSPersistentContainer(name: "stuff")
        container.loadPersistentStores { storeDescription, error in
            if let error = error { print("Error loading... \(error)") }
        }
    }
    
    func saveContext() {
        if container.viewContext.hasChanges {
            do { try container.viewContext.save()
            } catch { print("Error saving... \(error)") }
        }
    }
}

アプリのどこからでも

core.container

コンテナです

したがって、実際にはエンティティの数を取得するには、

let k = try? core.container.viewContext.count(for: NSFetchRequest(entityName: "Boat"))

0

特定の述語フェッチの数を見つけたい場合は、これが最良の方法だと思います。

NSError *err;
NSUInteger count = [context countForFetchRequest:fetch error:&err];

if(count > 0) {
NSLog(@"EXIST"); 
} else {
NSLog(@"NOT exist");
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.