Нужен универсальный конструктор FetchedResultsController (Swift)
Я создал метод для построения FRC:
private func buildFRC<T:NSManagedObject>(entity: T, sortKey: String)
-> NSFetchedResultsController<T>? {
let fetchRequest: NSFetchRequest = T.fetchRequest()
let sortDescriptor1 = NSSortDescriptor(key: sortKey, ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor1]
searchContext.reset()
var frc: NSFetchedResultsController<T>? =
NSFetchedResultsController<T>(
fetchRequest: fetchRequest as! NSFetchRequest<T>,
managedObjectContext: searchContext,
sectionNameKeyPath: nil,
cacheName: nil)
frc!.delegate = self
try? frc!.performFetch()
return frc
}
Я хочу назвать что-то вроде этого из замыкания:
self.frc = self.buildFRC(entity: ObjectName, sortKey: "trackName")
но я получаю эту ошибку:
Msgstr "Невозможно преобразовать значение типа 'ObjectName.Type' в ожидаемый тип аргумента 'NSManagedObject'".
Еще, ObjectName
это имя класса NSManagedObject
, Я попробовал себя, но в итоге я продолжаю гоняться за ошибками по кругу.
1 ответ
Объявление вашей функции не означает, что вы думаете.
private func buildFRC<T:NSManagedObject>(entity: T, sortKey: String) -> NSFetchedResultsController<T>?
Это означает, что T
должен быть подклассом NSManagedObject
и что первый аргумент должен быть экземпляром T. Когда ты называешь это так
self.frc = self.buildFRC(entity: ObjectName, sortKey: "trackName")
... вы передаете подкласс в качестве первого аргумента, когда ваше объявление ожидает экземпляр.
Это не сложно исправить, потому что вам не нужно включать T
в качестве аргумента. В общем случае, в обобщениях Swift вам не нужно передавать тип в качестве аргумента - тип исходит из того, как используется функция. Отбросьте этот аргумент и перепишите декларацию как
private func buildFRC<T:NSManagedObject>(sortKey: String) -> NSFetchedResultsController<T>? {
Затем вызовите функцию с чем-то вроде
self.frc: NSFetchedResultsController<ObjectName>? = self.buildFRC(sortKey: "trackName")
Свифт выяснит, что T
представляет собой ObjectName
в этом вызове и код будет работать.
На тангенциальной ноте ваш звонок searchContext.reset()
это опасно и, вероятно, не нужно. Если вы извлекаете некоторые объекты из контекста, а затем вызываете эту функцию, reset
приведет к тому, что все ранее выбранные объекты станут недействительными. Использование их приведет к краху вашего приложения.