I read much about Core Data.. but what is an efficient way to make a count over an Entity-Type (like SQL can do with SELECT count(1) ...). Now I just solved this task with s
I wrote a simple utility method for Swift 3 to fetch the count of the objects.
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
}
It is fairly easy to get a count of the total number of instances of an entity in Core Data:
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "MyEntity")
let count = context.countForFetchRequest(fetchRequest, error: nil)
I tested this in the simulator with a 400,000+ object count and the result was fairly fast (though not instantaneous).
I believe the easiest and the most efficient way to count objects is to set NSFetchRequest
result type to NSCountResultType
and execute it with NSManagedObjectContext countForFetchRequest:error:
method.
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
I don't know whether using NSFetchedResultsController is the most efficient way to accomplish your goal (but it may be). The explicit code to get the count of entity instances is below:
// 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];
let kBoat = try? yourContainer.viewContext.count(for: NSFetchRequest(entityName: "Boat"))
"Boat" is just the name of the entity from your data model screen:
What is the global yourContainer
?
To use core data, at some point in your app, one time only, you simply go
var yourContainer = NSPersistentContainer(name: "stuff")
where "stuff" is simply the name of the data model file.
You'd simply have a singleton for this,
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)") }
}
}
}
So from anywhere in the app
core.container
is your container,
So in practice to get the count of any entity, it's just
let k = try? core.container.viewContext.count(for: NSFetchRequest(entityName: "Boat"))
In 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
}