Below is my method in which there is fetch I make on a Managed object Class Appointment. I need to use same function for other similar managed object Classes. How do I pass
for the generic you can do something like this:
class FetchingDataHandler<T>{
func getAppointmentArray<T>(forClass : T, aPredicate : String , aModel : Any) -> [Any]
{
}
}
The good folks at Objc.io provide a really good approach for this. First declare a protocol which inherits 'NSFetchRequestResult' protocol as below.
protocol Managed: class, NSFetchRequestResult {
static var entityName: String { get }
}
Now we can provide a very convenient protocol extension for our protocol 'Managed'. We do the check 'Self: NSManagedObject' as we want the static method entity() of the NSManagedObject class to get the 'NSEntityDescription' describing the entity associated with our class. Particularly this way we get the entity name dynamically(and conveniently too) for all our ManagedObjects that conform to our protocol.
extension Managed where Self: NSManagedObject {
static var entityName: String { return entity().name! }
}
We now improve the protocol extension by providing a method which conveniently creates a fetch request and then calls a configuration block which might be used to configure the created fetch request by whoever calls it. At the end of this method we do a fetch using the created request.
extension Managed where Self: NSManagedObject {
static var entityName: String { return entity().name! }
//Continued
static func fetch(in context: NSManagedObjectContext, configurationBlock: (NSFetchRequest<Self>) -> ()) -> [Self] {
let request = NSFetchRequest<Self>(entityName: Self.entityName)
configurationBlock(request)
return try! context.fetch(request)
}
}
As you can see we do the following things here:
To see our protocol in action we can do this for your case:
class Appointment: NSManagedObject, Managed{
//properties for attributes
//etc...
//Will I get free implementation for entity name and a fetch method
//without writing extra code ?
//Yes why not
}
Testing our hard earned knowledge:
let aPredicate = "......
let context: NSManagedObjectContext.....
let appointments = Appointment.fetch(in: context) { fetchRequest in
//Configuration code like adding predicates and sort descriptors
fetchRequest.predicate = NSPredicate(format: aPredicate)
}
You can use the same pattern for any other ManagedObjects if they conform to the protocol. Eg a Doctor ManagedObject subclass conforming to our Managed protocol:
let aPredicate = "......
let context: NSManagedObjectContext.....
let doctors = Doctor.fetch(in: context) { fetchRequest in
//Configuration code like adding predicates and sort descriptors
fetchRequest.predicate = NSPredicate(format: aPredicate)
}