Last active
October 14, 2024 15:20
-
-
Save capttaco/adb38e0d37fbaf9c004e to your computer and use it in GitHub Desktop.
A utility protocol for custom NSManagedObjects that makes querying contexts simpler and more convenient. Requires Swift 2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import CoreData | |
protocol Fetchable | |
{ | |
typealias FetchableType: NSManagedObject | |
static func entityName() -> String | |
static func objectsInContext(context: NSManagedObjectContext, predicate: NSPredicate?, sortedBy: String?, ascending: Bool) throws -> [FetchableType] | |
static func singleObjectInContext(context: NSManagedObjectContext, predicate: NSPredicate?, sortedBy: String?, ascending: Bool) throws -> FetchableType? | |
static func objectCountInContext(context: NSManagedObjectContext, predicate: NSPredicate?) -> Int | |
static func fetchRequest(context: NSManagedObjectContext, predicate: NSPredicate?, sortedBy: String?, ascending: Bool) -> NSFetchRequest | |
} | |
extension Fetchable where Self : NSManagedObject, FetchableType == Self | |
{ | |
static func singleObjectInContext(context: NSManagedObjectContext, predicate: NSPredicate? = nil, sortedBy: String? = nil, ascending: Bool = false) throws -> FetchableType? | |
{ | |
let managedObjects: [FetchableType] = try objectsInContext(context, predicate: predicate, sortedBy: sortedBy, ascending: ascending) | |
guard managedObjects.count > 0 else { return nil } | |
return managedObjects.first | |
} | |
static func objectCountInContext(context: NSManagedObjectContext, predicate: NSPredicate? = nil) -> Int | |
{ | |
let request = fetchRequest(context, predicate: predicate) | |
let error: NSErrorPointer = nil; | |
let count = context.countForFetchRequest(request, error: error) | |
guard error != nil else { | |
NSLog("Error retrieving data %@, %@", error, error.debugDescription) | |
return 0; | |
} | |
return count; | |
} | |
static func objectsInContext(context: NSManagedObjectContext, predicate: NSPredicate? = nil, sortedBy: String? = nil, ascending: Bool = false) throws -> [FetchableType] | |
{ | |
let request = fetchRequest(context, predicate: predicate, sortedBy: sortedBy, ascending: ascending) | |
let fetchResults = try context.executeFetchRequest(request) | |
return fetchResults as! [FetchableType] | |
} | |
static func fetchRequest(context: NSManagedObjectContext, predicate: NSPredicate? = nil, sortedBy: String? = nil, ascending: Bool = false) -> NSFetchRequest | |
{ | |
let request = NSFetchRequest() | |
let entity = NSEntityDescription.entityForName(entityName(), inManagedObjectContext: context) | |
request.entity = entity | |
if predicate != nil { | |
request.predicate = predicate | |
} | |
if (sortedBy != nil) { | |
let sort = NSSortDescriptor(key: sortedBy, ascending: ascending) | |
let sortDescriptors = [sort] | |
request.sortDescriptors = sortDescriptors | |
} | |
return request | |
} | |
} |
Instead of protocol Fetchable
{
typealias FetchableType: NSManagedObject
wouldn't this be better?
protocol Fetchable
{
typealias FetchableType: NSManagedObject = Self
I got that advice on the Apple forums: https://forums.developer.apple.com/thread/14153
It should also be possible to provide a default implementation for the entityName in the protocol extension:
static func entityName() -> String {
return NSStringFromClass(self).componentsSeparatedByString(".").last!
}
And then use it in the fetchRequest()
function:
NSEntityDescription.entityForName(FetchableType.entityName(), inManagedObjectContext: context)
the guard on line 29 definitely should look like this:
guard error == nil else {
Instead of protocol Fetchable
{ typealias FetchableType: NSManagedObject
wouldn't this be better?
protocol Fetchable { typealias FetchableType: NSManagedObject = Self
Yes, that makes things easier. However, you still need to define the typealias when subclassing an NSManagedObject subclass.
class Image: NSManagedObject, Fetchable {
// This works, without typealias
}
class ThumbnailImage: Image {
// Need redefining of FetchableType if you want the Fetchable methods to return instances of ThumbnailImage
typealias FetchableType = ThumbnailImage
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can replace FetchableType with
Self
by the way and simplify things!