Search code examples
iosswiftmagicalrecord

How to use generics to return all objects for specific type of NSManagedObject?


This is what I need to achieve:

extension NSManagedObject {
    class func all<T: Self>(in context: NSManagedObjectContext) -> [T] { //error: Expected a class type or protocol-constrained type restricting '
        return mr_findAll(in: context) as! [T]
    }
}

And I would like to use it like this:

let persons = Person.all(in: context)
let hotels = Hotel.all(in: context)

Is it possible at all?

Person and Hotel inherits from NSManagedObject.


Solution

  • As a fetch request is already generic this can be accomplished only with a protocol extension and associated type, an NSManagedObject extension doesn't work without any type cast or annotation.

    protocol Managed
    {
        associatedtype ManagedType: NSManagedObject = Self
        static var entityName : String { get }
        static func all(in context: NSManagedObjectContext) throws -> [ManagedType]
    }
    
    extension Managed where Self : NSManagedObject {
        static var entityName : String { return String(describing:self) }
    
        static func all(in context: NSManagedObjectContext) throws -> [ManagedType] {
            let request = NSFetchRequest<ManagedType>(entityName: entityName)
            return try context.fetch(request)
        }
    }
    

    Just add conformance to Managed to all your NSManagedObject subclasses then you can use

    let persons = Person.all(in: context)
    let hotels = Hotel.all(in: context)