Convert request Function to Generic type

I am trying to convert my below fetch request code from core data to generic type.

let request = NSPredicate(format: "name == %@ AND password == %@ AND type == %@", "admin", "admin", "admin")
let fetchReq : NSFetchRequest = UserRegistration.fetchRequest()
fetchReq.predicate = request
let adminDetail :[UserRegistration] = DatabaseEngine.fetch(fetchRequest: fetchReq)!

Converted so far:

extension UIViewController{
    class func getData<T: NSManagedObject>(req: NSPredicate) -> T{
        let fetchReq : NSFetchRequest = T.fetchRequest()
        fetchReq.predicate = req
        return DatabaseEngine.fetch(fetchRequest: fetchReq as! NSFetchRequest<NSManagedObject>)! as! T

    }
}

DatabaseEngine.fetch function.

static func fetch (fetchRequest: NSFetchRequest<T> = NSFetchRequest(), context:NSManagedObjectContext = kApplicationDelegate.managedObjectContext) -> [T]? {

    let entity =  NSEntityDescription.entity(forEntityName: typeName(some:T.self)
        , in:context)
    // Configure Fetch Request
    fetchRequest.entity = entity
    do {
        return try  context.fetch(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) as? [T]
    } catch {

        //let fetchError = error as NSError
        // return nil

    }
    return nil
}

But no results any more. Anybody help me to convert this code with few explaining lines. Ans will be appreciated sure.


According to my comment I recommend to use a protocol with extension for example

protocol Fetchable
{
    associatedtype FetchableType: NSManagedObject = Self

    static var entityName : String { get }
    static var managedObjectContext : NSManagedObjectContext { get }
    static func objects(for predicate: NSPredicate?) throws -> [FetchableType]
}

extension Fetchable where Self : NSManagedObject, FetchableType == Self
{
    static var entityName : String {
        return NSStringFromClass(self).components(separatedBy: ".").last!
    }

    static var managedObjectContext : NSManagedObjectContext {
        return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    }

    static func objects(for predicate: NSPredicate?) throws -> [FetchableType]
    {
        let request = NSFetchRequest<FetchableType>(entityName: entityName)
        request.predicate = predicate
        return try managedObjectContext.fetch(request)
    }
}

Change (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext to the reference to your managed object context.

Make all NSManagedObject subclasses adopt Fetchable. There is no extra code needed in the subclasses.

Now you can get the data with

do {
   let predicate = NSPredicate(format: ...
   let objects = try MyEntity.objects(for: predicate)
} catch {
    print(error)
}

That's all, objects are [MyEntity] without any type casting and always non-optional on success.

The protocol is easily extendable by default sorting descriptors, sorting directions etc.