From 7b659402867cba6be845ceed767527fc4015bd02 Mon Sep 17 00:00:00 2001 From: Christopher Pickslay Date: Thu, 18 Dec 2014 10:43:21 -0800 Subject: [PATCH 1/2] Added count() method to SugarRecordObjectProtocol so it can be called directly from an object type (e.g., SomeObjectClass.count()), rather than via all().count(). Optimized core data implementation of count() to use `NSManagedObjectContext.countForFetchRequest()` instead of loading all instances of the object into memory and counting them. --- .../SugarRecordContextProtocol.swift | 5 +++++ .../Protocols/SugarRecordObjectProtocol.swift | 8 ++++++++ library/Core/SugarRecordFinder.swift | 20 ++++++------------- .../Base/NSManagedObject+SugarRecord.swift | 15 ++++++++++++++ .../CoreData/Base/SugarRecordCDContext.swift | 13 ++++++++++++ library/Realm/RLMObject+SugarRecord.swift | 11 ++++++++++ library/Realm/SugarRecordRLMContext.swift | 13 ++++++++++++ spec/Models/CoreDataObjectTests.swift | 2 +- spec/Models/RealmObjectTests.swift | 2 +- 9 files changed, 73 insertions(+), 16 deletions(-) diff --git a/library/Core/Protocols/SugarRecordContextProtocol.swift b/library/Core/Protocols/SugarRecordContextProtocol.swift index c60bec7b..6ea677a0 100644 --- a/library/Core/Protocols/SugarRecordContextProtocol.swift +++ b/library/Core/Protocols/SugarRecordContextProtocol.swift @@ -49,4 +49,9 @@ public protocol SugarRecordContext * Executes the finder query to return filtered values */ func find(finder: SugarRecordFinder) -> [AnyObject] + + /** + * Count the number of entities of the given type + */ + func count(objectClass: AnyClass) -> Int } \ No newline at end of file diff --git a/library/Core/Protocols/SugarRecordObjectProtocol.swift b/library/Core/Protocols/SugarRecordObjectProtocol.swift index 1b9193aa..21d122ad 100644 --- a/library/Core/Protocols/SugarRecordObjectProtocol.swift +++ b/library/Core/Protocols/SugarRecordObjectProtocol.swift @@ -71,6 +71,14 @@ public protocol SugarRecordObjectProtocol class func all() -> SugarRecordFinder + //MARK: - Count + + /** + * Returns the count of items of the class type + */ + class func count() -> Int + + //MARK: - Deletion /** diff --git a/library/Core/SugarRecordFinder.swift b/library/Core/SugarRecordFinder.swift index b151e758..f64a64f4 100644 --- a/library/Core/SugarRecordFinder.swift +++ b/library/Core/SugarRecordFinder.swift @@ -397,13 +397,11 @@ public class SugarRecordFinder */ public func count() -> Int { - let objects: [AnyObject]? = find() - if objects != nil { - return objects!.count - } - else { - return 0 - } + var count: Int = 0 + SugarRecord.operation(stackType!, closure: { (context) -> () in + count = context.count(self.objectClass!) + }) + return count } /** @@ -415,12 +413,6 @@ public class SugarRecordFinder */ public func count(inContext context:SugarRecordContext) -> Int { - let objects: [AnyObject]? = find(inContext: context) - if objects != nil { - return objects!.count - } - else { - return 0 - } + return context.count(self.objectClass!) } } \ No newline at end of file diff --git a/library/CoreData/Base/NSManagedObject+SugarRecord.swift b/library/CoreData/Base/NSManagedObject+SugarRecord.swift index 0996263a..035c7520 100644 --- a/library/CoreData/Base/NSManagedObject+SugarRecord.swift +++ b/library/CoreData/Base/NSManagedObject+SugarRecord.swift @@ -165,6 +165,21 @@ extension NSManagedObject: SugarRecordObjectProtocol return finder } + //MARK: - Count + + /** + Returns a the count of elements of this type + + :returns: Int + */ + public class func count() -> Int + { + var finder: SugarRecordFinder = SugarRecordFinder() + finder.objectClass = self + finder.stackType = stackType() + return finder.count() + } + //MARK: - Deletion /** diff --git a/library/CoreData/Base/SugarRecordCDContext.swift b/library/CoreData/Base/SugarRecordCDContext.swift index 4496ba68..f4ea487b 100644 --- a/library/CoreData/Base/SugarRecordCDContext.swift +++ b/library/CoreData/Base/SugarRecordCDContext.swift @@ -172,6 +172,19 @@ public class SugarRecordCDContext: SugarRecordContext SugarRecordLogger.logLevelInfo.log("Deleted \(objects.count) objects") } + /** + * Count the number of entities of the given type + */ + public func count(objectClass: AnyClass) -> Int + { + let managedObjectClass: NSManagedObject.Type = objectClass as NSManagedObject.Type + let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: managedObjectClass.modelName()) + var error: NSError? + var count = self.contextCD.countForFetchRequest(fetchRequest, error: &error) + SugarRecordLogger.logLevelInfo.log("Found \(count) objects in database") + return count + } + //MARK: - HELPER METHODS diff --git a/library/Realm/RLMObject+SugarRecord.swift b/library/Realm/RLMObject+SugarRecord.swift index c4210a55..631bdcbf 100644 --- a/library/Realm/RLMObject+SugarRecord.swift +++ b/library/Realm/RLMObject+SugarRecord.swift @@ -167,6 +167,17 @@ extension RLMObject: SugarRecordObjectProtocol } + //MARK: - Count + + /** + * Returns the count of items of the class type + */ + public class func count() -> Int + { + return all().count() + } + + //MARK: - Deletion /** diff --git a/library/Realm/SugarRecordRLMContext.swift b/library/Realm/SugarRecordRLMContext.swift index 9db73359..264c9b12 100644 --- a/library/Realm/SugarRecordRLMContext.swift +++ b/library/Realm/SugarRecordRLMContext.swift @@ -166,4 +166,17 @@ public class SugarRecordRLMContext: SugarRecordContext } SugarRecordLogger.logLevelInfo.log("Deleted \(objects.count) objects") } + + + /** + * Count the number of entities of the given type + */ + public func count(objectClass: AnyClass) -> Int + { + let objectClass: RLMObject.Type = objectClass as RLMObject.Type + var objects: RLMResults? = nil + objects = objectClass.allObjectsInRealm(self.realmContext) + return Int(objects!.count) + } + } \ No newline at end of file diff --git a/spec/Models/CoreDataObjectTests.swift b/spec/Models/CoreDataObjectTests.swift index 4801dbda..12dd4f23 100644 --- a/spec/Models/CoreDataObjectTests.swift +++ b/spec/Models/CoreDataObjectTests.swift @@ -143,7 +143,7 @@ class CoreDataObjectTests: XCTestCase coreDataObject2!.city = "TestCity2" coreDataObject2!.birth = NSDate() let saved2: Bool = coreDataObject2!.save() - XCTAssertEqual(CoreDataObject.all().count(), 2, "The count should be equal to 2") + XCTAssertEqual(CoreDataObject.count(), 2, "The count should be equal to 2") coreDataObject!.beginWriting().delete().endWriting() coreDataObject2!.beginWriting().delete().endWriting() } diff --git a/spec/Models/RealmObjectTests.swift b/spec/Models/RealmObjectTests.swift index 2639a697..6dcb6f0d 100644 --- a/spec/Models/RealmObjectTests.swift +++ b/spec/Models/RealmObjectTests.swift @@ -137,7 +137,7 @@ class RealmObjectTests: XCTestCase realmObject2!.city = "TestCity2" realmObject2!.birthday = NSDate() let saved2: Bool = realmObject2!.save() - XCTAssertEqual(RealmObject.all().count(), 2, "The count should be equal to 2") + XCTAssertEqual(RealmObject.count(), 2, "The count should be equal to 2") realmObject!.beginWriting().delete().endWriting() realmObject2!.beginWriting().delete().endWriting() } From 608890890cf4dafd9702ca3b22bd555f8fe800e5 Mon Sep 17 00:00:00 2001 From: Christopher Pickslay Date: Thu, 18 Dec 2014 14:57:19 -0800 Subject: [PATCH 2/2] allow count to work when a predicate is passed to limit the results --- library/Core/Protocols/SugarRecordContextProtocol.swift | 2 +- library/Core/SugarRecordFinder.swift | 4 ++-- library/CoreData/Base/SugarRecordCDContext.swift | 3 ++- library/Realm/SugarRecordRLMContext.swift | 9 +++++++-- spec/Models/CoreDataObjectTests.swift | 1 + spec/Models/RealmObjectTests.swift | 1 + 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/library/Core/Protocols/SugarRecordContextProtocol.swift b/library/Core/Protocols/SugarRecordContextProtocol.swift index 6ea677a0..0ba562dd 100644 --- a/library/Core/Protocols/SugarRecordContextProtocol.swift +++ b/library/Core/Protocols/SugarRecordContextProtocol.swift @@ -53,5 +53,5 @@ public protocol SugarRecordContext /** * Count the number of entities of the given type */ - func count(objectClass: AnyClass) -> Int + func count(objectClass: AnyClass, predicate: NSPredicate?) -> Int } \ No newline at end of file diff --git a/library/Core/SugarRecordFinder.swift b/library/Core/SugarRecordFinder.swift index f64a64f4..68ff92aa 100644 --- a/library/Core/SugarRecordFinder.swift +++ b/library/Core/SugarRecordFinder.swift @@ -399,7 +399,7 @@ public class SugarRecordFinder { var count: Int = 0 SugarRecord.operation(stackType!, closure: { (context) -> () in - count = context.count(self.objectClass!) + count = context.count(self.objectClass!, predicate: self.predicate) }) return count } @@ -413,6 +413,6 @@ public class SugarRecordFinder */ public func count(inContext context:SugarRecordContext) -> Int { - return context.count(self.objectClass!) + return context.count(self.objectClass!, predicate: self.predicate) } } \ No newline at end of file diff --git a/library/CoreData/Base/SugarRecordCDContext.swift b/library/CoreData/Base/SugarRecordCDContext.swift index f4ea487b..9c07de01 100644 --- a/library/CoreData/Base/SugarRecordCDContext.swift +++ b/library/CoreData/Base/SugarRecordCDContext.swift @@ -175,10 +175,11 @@ public class SugarRecordCDContext: SugarRecordContext /** * Count the number of entities of the given type */ - public func count(objectClass: AnyClass) -> Int + public func count(objectClass: AnyClass, predicate: NSPredicate? = nil) -> Int { let managedObjectClass: NSManagedObject.Type = objectClass as NSManagedObject.Type let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: managedObjectClass.modelName()) + fetchRequest.predicate = predicate var error: NSError? var count = self.contextCD.countForFetchRequest(fetchRequest, error: &error) SugarRecordLogger.logLevelInfo.log("Found \(count) objects in database") diff --git a/library/Realm/SugarRecordRLMContext.swift b/library/Realm/SugarRecordRLMContext.swift index 264c9b12..1bcc7652 100644 --- a/library/Realm/SugarRecordRLMContext.swift +++ b/library/Realm/SugarRecordRLMContext.swift @@ -171,11 +171,16 @@ public class SugarRecordRLMContext: SugarRecordContext /** * Count the number of entities of the given type */ - public func count(objectClass: AnyClass) -> Int + public func count(objectClass: AnyClass, predicate: NSPredicate? = nil) -> Int { let objectClass: RLMObject.Type = objectClass as RLMObject.Type var objects: RLMResults? = nil - objects = objectClass.allObjectsInRealm(self.realmContext) + if predicate != nil { + objects = objectClass.objectsWithPredicate(predicate) + } + else { + objects = objectClass.allObjectsInRealm(self.realmContext) + } return Int(objects!.count) } diff --git a/spec/Models/CoreDataObjectTests.swift b/spec/Models/CoreDataObjectTests.swift index 12dd4f23..ed9ea488 100644 --- a/spec/Models/CoreDataObjectTests.swift +++ b/spec/Models/CoreDataObjectTests.swift @@ -144,6 +144,7 @@ class CoreDataObjectTests: XCTestCase coreDataObject2!.birth = NSDate() let saved2: Bool = coreDataObject2!.save() XCTAssertEqual(CoreDataObject.count(), 2, "The count should be equal to 2") + XCTAssertEqual(CoreDataObject.by("name", equalTo: "'Realmy2'").count(), 1, "The count should be equal to 1") coreDataObject!.beginWriting().delete().endWriting() coreDataObject2!.beginWriting().delete().endWriting() } diff --git a/spec/Models/RealmObjectTests.swift b/spec/Models/RealmObjectTests.swift index 6dcb6f0d..004e8641 100644 --- a/spec/Models/RealmObjectTests.swift +++ b/spec/Models/RealmObjectTests.swift @@ -138,6 +138,7 @@ class RealmObjectTests: XCTestCase realmObject2!.birthday = NSDate() let saved2: Bool = realmObject2!.save() XCTAssertEqual(RealmObject.count(), 2, "The count should be equal to 2") + XCTAssertEqual(RealmObject.by("name", equalTo: "'Realmy2'").count(), 1, "The count should be equal to 1") realmObject!.beginWriting().delete().endWriting() realmObject2!.beginWriting().delete().endWriting() }