Cocoa Core Data cara yang efisien untuk menghitung entitas

174

Saya membaca banyak tentang Core Data .. tapi apa cara yang efisien untuk membuat perhitungan atas Entity-Type (seperti SQL dapat dilakukan dengan SELECT count (1) ...). Sekarang saya baru saja menyelesaikan tugas ini dengan memilih semua dengan NSFetchedResultsControllerdan mendapatkan hitungan NSArray! Saya yakin ini bukan cara terbaik ...

erazorx
sumber

Jawaban:

303

Saya tidak tahu apakah menggunakan NSFetchedResultsController adalah cara yang paling efisien untuk mencapai tujuan Anda (tetapi mungkin saja). Kode eksplisit untuk mendapatkan jumlah instance entitas adalah di bawah ini:

// 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];
Barry Wark
sumber
1
Pada Leopard Anda ingin menggunakan countForFetchRequest: dan tidak mengeksekusiFetchRequest:
IlDan
Dan lewati untuk mengatur predikat. Tidak ada predikat: dapatkan semua objek yang cocok dengan deskripsi entitas
IlDan
4
Hanya FYI, hitung == 0 jika tidak ada hasil untuk permintaan spesifik, NSNotFound = NSIntegerMax, jadi '// Handel error' tidak akan dieksekusi jika tidak ada hasil.
Intentss
Apakah ada kesalahan ketik pada: setIncludesSubentities? Saya pikir dokumentasi menunjukkan huruf kecil "e" di "entitas" daripada huruf besar "E" dalam kode contoh.
Mike
2
@ LarsSchneider dokumentasi untuk countForFetchRequest:error:negara yang NSNotFounddikembalikan jika terjadi kesalahan. Secara umum, NSErrorpenanganan dalam konvensi Kakao adalah bahwa nilai errtidak terdefinisi (dan sering berbahaya) jika tidak terjadi kesalahan.
Barry Wark
61

Agar jelas, Anda tidak menghitung entitas, tetapi instance entitas tertentu. (Untuk benar-benar menghitung entitas, tanyakan model objek yang dikelola untuk menghitung entitasnya.)

Untuk menghitung semua instance dari entitas yang diberikan tanpa mengambil semua data, gunakan -countForFetchRequest:.

Sebagai contoh:

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;
Jim Correia
sumber
32

Cepat

Cukup mudah untuk mendapatkan jumlah total instance dari entitas dalam Core Data:

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

Saya menguji ini di simulator dengan jumlah objek 400.000 + dan hasilnya cukup cepat (meskipun tidak instan).

Suragch
sumber
23

Saya hanya akan menambahkan itu untuk membuatnya lebih efisien ... dan karena itu hanya hitungan, Anda tidak benar-benar membutuhkan nilai properti dan tentu saja seperti salah satu contoh kode di atas Anda tidak perlu sub-entitas juga.

Jadi, kodenya harus seperti ini:

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

Semoga ini bisa membantu.

Oscar Salguero
sumber
10

Saya percaya cara termudah dan paling efisien untuk menghitung objek adalah dengan menetapkan NSFetchRequesttipe hasil NSCountResultTypedan menjalankannya dengan NSManagedObjectContext countForFetchRequest:error:metode.

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
Yuriy Pavlyshak
sumber
6

Saya menulis metode utilitas sederhana untuk Swift 3 untuk mengambil hitungan objek.

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
}
jarora
sumber
3

Dalam 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
}
Philippe H. Regenass
sumber
1

Ini benar-benar hanya ini:

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

"Boat" hanyalah nama entitas dari layar model data Anda:

masukkan deskripsi gambar di sini

Apa itu global yourContainer?

Untuk menggunakan data inti, pada titik tertentu di aplikasi Anda, satu kali saja, Anda cukup pergi

var yourContainer = NSPersistentContainer(name: "stuff")

di mana "barang" hanyalah nama file model data.

masukkan deskripsi gambar di sini

Anda hanya akan memiliki satu untuk ini,

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)") }
        }
    }
}

Jadi dari mana saja di aplikasi

core.container

adalah wadahmu,

Jadi dalam praktiknya untuk mendapatkan hitungan entitas apa pun, hanya saja

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

Jika Anda ingin menemukan jumlah untuk pengambilan predicated tertentu, saya yakin ini adalah cara terbaik:

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

if(count > 0) {
NSLog(@"EXIST"); 
} else {
NSLog(@"NOT exist");
}
Umit Kaya
sumber