Проблема

*** Завершение работы приложения из-за необработанного исключения «NSUnknownKeyException», причина: «[valueForUndefinedKey:]:
этот класс не совместим со значением ключа для активного ключа. '
Благодаря @GrahamPerks ответу на этот ТАК * вопрос я вставил точку прерывания исключения в свой код, которая теперь приостанавливает выполнение в этой строке ...
static var entityActive: Bool {
return entity.value(forKey: "active") as! Bool // <-- PAUSES AT THIS LINE
}
Это, очевидно, требует дальнейшего объяснения ...
Фон
Я пишу приложение Core Data, в котором используется общий источник данных табличного представления и делегат, более или менее настроенный в соответствии с книгой Флориана Куглера «Основные данные», опубликованной в 2017 году objc.io .
Я успешно связал три отдельных UITableViewController
с этим общим источником данных / делегатом. Я использую одну основную раскадровку, и эти три контроллера связаны с тремя UISplitViewController
основными / подробными представлениями.
Я удалил автоматически сгенерированные соединения dataSource и делегата внутри раскадровки UITableView
s (хотя, если я оставлю или удалю эти соединения, похоже, не имеет значения).
Если я закомментирую код для static var entityActive
выше, проект будет успешно построен и запущен.
Мой код использует метод UITableViewDelegate
tableView(_, willDisplay:, forRowAt:)
для изменения .textColor
текста и .backgroundColor
ячеек на основе атрибута «active», хранящегося в виде логического значения скалярного типа для каждой сущности.
Для ясности я пытаюсь получить атрибут "активный" (у каждого объекта в моей модели данных есть общий атрибут "активный") для каждого NSManagedObject
для объекта. Значение этого «активного» атрибута (Bool
true
или false
) для каждого объекта затем используется для форматирования ячейки в операторе if ... else в следующем коде.
Чтобы попытаться максимизировать повторное использование кода и свести к минимуму повторение кода, я также поместил этот метод делегата в мой общий источник данных / класс делегата.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let entityObjectActive = T.entityActive
if entityObjectActive == true {
cell.textLabel?.textColor = UIColor.black
cell.detailTextLabel?.textColor = UIColor.darkGray
cell.backgroundColor = UIColor.white
} else if entityObjectActive == false {
cell.textLabel?.textColor = UIColor.lightGray
cell.detailTextLabel?.textColor = UIColor.lightGray
cell.backgroundColor = UIColor.clear
}
}
Компилятор не жалуется.
Кажется, я могу использовать универсальный тип T
(представляющий сущности базовых данных), чтобы связать статическое свойство entityActive
с моим экземпляром entityObjectActive
- так что, похоже, это работает ...
let entityObjectActive = T.entityActive
Для подтверждения у меня есть следующее:
общий класс источника данных ....
class MyDataSource<T: Managed,
Delegate: TableViewDataSourceDelegate>:
NSObject,
UITableViewDataSource,
UITableViewDelegate,
NSFetchedResultsControllerDelegate {
// lots of code...
}
протокол ...
protocol Managed: class, NSFetchRequestResult {
static var entity: NSEntityDescription { get }
static var entityActive: Bool { get } }
}
и расширение ...
extension Managed where Self: NSManagedObject {
static var entity: NSEntityDescription { return entity() }
static var entityActive: Bool {
return entity.value(forKey: "active") as! Bool
}
}
Попытки решения проблемы
Я немного читал, пытаясь решить мою проблему, включая обзор многих блогов (о том, как настроить универсальные источники в общих источниках данных и источниках представления общих таблиц), а также множество вопросов и ответов SO, в частности ...
Как исправить ошибку: этот класс не совместим со значением ключа для tableView ключа. '
Неопределенное исключение: этот класс не соответствует кодировке значения ключа
setValue: forUndefinedKey: этот класс не соответствует значению ключа для кода
Кажется, что все вопросы и ответы по SO напрямую связаны с проблемой соединений IB внутри раскадровок. Может быть, это тоже моя проблема, но если это так, то мне кажется, что она очень хорошо спрятана.
Любая помощь или совет, пожалуйста?
PS: я изучаю Swift после того, как я долгое время работал программистом в Obj-C, и я действительно борюсь со смещением парадигмы Generics Protocols Extensions, так что может случиться так, что мое использование универсальных типов неверно?