Нужен универсальный конструктор 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 приведет к тому, что все ранее выбранные объекты станут недействительными. Использование их приведет к краху вашего приложения.

Другие вопросы по тегам