I want to state that I am fairly new to Swift and I was exploring CoreData concepts. I tried to test with a ToDo list app which on welcome screen shows user created task categories and upon clicking on any category the user will see all the tasks in that group. I tried to create a generic class something like ToDoListViewController<T: NSManagedObject>
and to implement functionality available for both view controllers(CategoryViewController
, TaskViewController
). In that class I created a function loadItems
which takes a predicate
as an argument and populates the page with items from a fetch request. So the code roughly looks like this:
class ToDoListViewController<T: NSManagedObject>: UITableViewController {
func loadItems(predicate: NSPredicate? = nil) {
let request: NSFetchRequest<T> = T.fetchRequest()
if predicate != nil {
request.predicate = predicate!
}
do {
let items = try context.fetch(request)
// Do something
} catch {
print("Error fetching items from context \(error)")
}
}
}
The issue is that when I try to compile I get error:
Cannot assign value of type
NSFetchRequest<NSFetchRequestResult>
to typeNSFetchRequest<T>
when assigning request
variable. But if I force cast NSFetchRequest<NSFetchRequestResult>
to NSFetchRequest<T>
like this:
let request: NSFetchRequest<T> = T.fetchRequest() as! NSFetchRequest<T>
everything works fine. Since The NSManagedObject
documentation clearly states that it conforms to NSFetchRequestResult
protocol, why do I have to force cast NSFetchRequest<NSFetchRequestResult>
to NSFetchRequest<T>
?
You have to cast the type because the generic type of NSFetchRequest
– which is constrained to NSFetchRequestResult
– can also be NSDictionary
or NSNumber
or NSManagedObjectID
.
Rather than making a generic type more generic I recommend to use a protocol with associated types like described here