不存在的核心数据管理对象属性的NSunknownyKeyException
我有一个依赖核心数据
持续存在的应用程序。 该应用程序正在使用MVVM
架构以促进测试。
开发环境是macBook pro
(m1 max)运行macOS 12.4
和xcode 14 beta 2
到目前为止,一切都很好,直到我尝试尝试要将一个新的Entity
添加到与另一个实体有关系(多一对)的模型中。试图实例化这些实体之一,导致与定义关系的属性关联的nsunknownekyexception
,因此我从模型中删除了此关系>,并重新运行了测试。
令我惊讶的是,错误持续存在
,而且我一直无法解决它,因为尽管有以下内容:
- 清洁构建文件夹
- 删除派生数据,重新启动
xcode
XCODE - 重命名cristendentity(错误)坚持不懈,仅具有不同的
实体
名称) - delete
entity
,然后添加到模型 - 关闭代码 - 基因并定义MO子类手动
- 检查核心数据xml-这看起来无可示感并且没有任何残留属性可能导致
- 来自模拟器
- 擦除设置的问题删除应用程序,然后重新启动模拟器
- 卸载,然后重新安装xcode
我尚未尝试过的一件事就是通过xcode 13运行代码(这是一台新计算机因此,我都很热情,直接去找beta
,这可能是一个错误!),因此很快就会这样做。
目前看来,与核心数据
模型和实体之间的关系有关的东西似乎藏在我找不到的地方,但这可能是工具中的错误。当然,问题是我无法继续使用编译器错误来开发该应用程序。任何想法或指导都会非常欢迎...
在有问题的托管托管子类(便利方法)上扩展:
extension Prescription {
// MARK: - INTERNAL TYPES
enum PointOfCareContext: String, CustomStringConvertible {
case premedication, perioperative, postoperative, hospitalised
var description: String {
return self.rawValue.capitalized
}
}
// MARK: - PROPERTIES
var drug: Drug {
get { guard let drug = cd_drug else {
fatalError("Persistent store corrupted: Prescription is missing relationship to Drug.")
}
return drug
}
set { cd_drug = newValue }
}
var timePrescribed: Date {
get { guard let timePrescribed = cd_timePrescribed else {
fatalError("Persistent store corrupted: Prescription is missing timePrescribed.")
}
return timePrescribed
}
set { cd_timePrescribed = newValue }
}
/// When the drug should be administered
/// Passing nil to this property indicates the drug should be given asap (so will return current Date)
var timeScheduled: Date? {
get { guard let timeScheduled = cd_timeScheduled else {
return Date.now
}
return timeScheduled
}
set { cd_timeScheduled = newValue }
}
/// When the drug was administered
/// Nil indicates not given yet
var timeAdministered: Date? {
get { return cd_timeAdministered }
set { cd_timeScheduled = newValue }
}
var doseRate: Measurement<UnitDensity> {
get {
if (cd_doseRate != 0) {
fatalError("Persistent store corrupted: Prescription doseRate == 0.")
}
return Measurement(value: cd_doseRate, unit: .milligramsPerKilogram)
}
set {
cd_doseRate = newValue.converted(to: .milligramsPerKilogram).value
}
}
var dose: Measurement<UnitMass> {
get {
return Measurement(value: cd_dose, unit: .milligrams)
}
set {
cd_doseRate = newValue.converted(to: .milligrams).value
}
}
var doseVolume: Measurement<UnitVolume> {
get {
return Measurement(value: cd_doseVolume, unit: .milliliters)
}
set {
cd_doseVolume = newValue.converted(to: .milliliters).value
}
}
var context: PointOfCareContext {
get {
guard let contextValue = cd_context, let context = PointOfCareContext(rawValue: contextValue) else {
fatalError("Persistent store corrupted: Prescription has an invalid administration context [\(cd_context ?? "")]")
}
return context
}
set {
cd_context = newValue.rawValue
}
}
视图模型,该模型是测试的主题:
extension ProcedurePlanView {
class ViewModel: NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
// swiftlint:disable:next nesting
typealias Dependencies = HasParameterController & HasPersistence & HasViewFactory
private let parameterController: ParameterController
private let persistenceService: PersistenceService
private let viewFactory: ViewFactory
private let frc: NSFetchedResultsController<Prescription>
let patient: Patient
let procedure: Procedure
// MARK: - TabOne conformance
@Published var clinician: String = ""
@Published var anaesthetist: String = ""
@Published var assistant: String = ""
@Published var history: String = ""
@Published var tasks: String = ""
@Published var complications: String = ""
@Published var mucousMembraneColor: MucousMembraneColor?
@Published var asaGrade: ASAGrade?
@Published var cannulaPosition: CannulaPosition?
@Published var cannulaSide: Side?
@Published var cannulaGauge: PeripheralCannulaGauge?
@Published var auscultation: String = ""
@Published var temperament: Double?
@Published var airwayType: AirwayType?
@Published var airwaySize: String?
@Published var airwayCuffStatus: Bool?
@Published var breathingSystem: BreathingSystemType?
@Published var prescriptions: [Prescription]?
// MARK: - INIT
init(procedure: Procedure? = nil, patient: Patient, dependencies: Dependencies) {
self.persistenceService = dependencies.persistenceService
self.parameterController = dependencies.parameterController
self.viewFactory = dependencies.viewFactory
var currentProcedure: Procedure?
if let procedure {
currentProcedure = procedure
} else {
currentProcedure = Procedure(context: persistenceService.viewContext)
currentProcedure!.patient = patient
}
let frc = ProcedurePlanView.ViewModel.createPremedFRCUsing(
patient,
procedure: currentProcedure!,
context: dependencies.persistenceService.viewContext
)
self.frc = frc
self.patient = patient
self.procedure = currentProcedure!
self.prescriptions = ProcedurePlanView.ViewModel.performInitialFetchFor(frc)
super.init()
self.frc.delegate = self
}
// MARK: - PUBLIC METHODS
func makeParameterGridView() -> some View {
viewFactory.makeParameterGridView(patient: patient)
}
func resetForm() {
clinician.removeAll()
anaesthetist.removeAll()
assistant.removeAll()
history.removeAll()
tasks.removeAll()
complications.removeAll()
mucousMembraneColor = nil
asaGrade = nil
cannulaPosition = nil
cannulaSide = nil
cannulaGauge = nil
auscultation.removeAll()
temperament = nil
airwayType = nil
airwaySize = nil
airwayCuffStatus = nil
breathingSystem = nil
}
func save() {
procedure.patient = patient
procedure.clinican = clinician
procedure.anaesthetist = anaesthetist
procedure.assistant = assistant
procedure.history = history
procedure.tasks = tasks
procedure.complications = complications
procedure.asaGrade = asaGrade
Logger.viewModel.warning("Incomplete implementaton of cannula data in Procedure managed object and VM")
_ = Observation.create(
in: persistenceService.viewContext,
patient: patient,
parameter: parameterController.getParameterWith(name: .mucousMembraneColor),
stringValue: mucousMembraneColor?.rawValue ?? "Unknown"
)
do {
try persistenceService.viewContext.saveIfNeeded()
} catch {
fatalError(
"Unable to save context \(persistenceService.viewContext) to store due to error: \(error.localizedDescription)"
)
}
}
// MARK: - PRIVATE METHODS
private static func createPremedFRCUsing(_ patient: Patient, procedure: Procedure, context: NSManagedObjectContext) -> NSFetchedResultsController<Prescription> {
let request = Prescription.fetchRequest()
request.predicate = NSPredicate(format: "procedure == %@", procedure)
request.sortDescriptors = [NSSortDescriptor(keyPath: \Prescription.cd_drug?.cd_nameGeneric, ascending: false)]
let frc = NSFetchedResultsController(
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: nil,
cacheName: nil
)
return frc
}
private static func performInitialFetchFor(_ frc: NSFetchedResultsController<Prescription>) -> [Prescription] {
do {
try frc.performFetch()
} catch {
Logger.persistenceService.critical(
"FRC failed to fetch Drugs from persistent store: \(error.localizedDescription)"
)
}
return frc.fetchedObjects ?? []
}
// MARK: - NSFetchedResultsControllerDelegate conformance
internal func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
let newPrescriptions = controller.fetchedObjects as? [Prescription] ?? []
prescriptions = newPrescriptions
}
}
}
I have an app that relies on Core Data
for persistence.
The app is using MVVM
architecture in order to facilitate testing.
The dev environment is a MacBook Pro
(M1 Max) running macOS 12.4
and Xcode 14 beta 2
So far everything has been working well until I attempted to add a new entity
to my Model that had a relationship (many-to-one) to another entity. Attempting to instantiate one of these entities resulted in a NSUnknownKeyException
associated with the property that defined the relationship, so I deleted this relationship
from the model and re-ran the test.
Much to my surprise, the error persisted
and I have been singularly unable to resolve it since despite the following:
- Clean build folder
- Delete derived data, reboot
XCode
- Rename offending entity (error persists, just with the different
entity
name) - Delete
entity
and add back into the Model - Turn off code-gen and defined the MO subclass manually
- Check Core Data XML - this looks unremarkable and there are no residual properties that could be causing the problem
- Delete app from Simulator
- Erase settings then restart Simulator
- Uninstall and then re-install Xcode
The one thing I haven't tried yet is to run the code through Xcode 13 (it's a new machine so I was all enthusiastic and went straight for the beta
which might have been a mistake!) so will be doing that shortly.
For now it seems that something relating to the Core Data
model and relationships between entities is hiding out somewhere I can't find it but it could be a bug in the tooling. The problem of course is that I can't continue to develop the app with a compiler error I can't clear. Any thoughts or guidance would be very welcome...
Xcode Model interface for Prescription
Xcode Model interface for Procedure
.xcdatamodeld XML for Prescription
Extension on the offending ManagedObject subclass (convenience methods):
extension Prescription {
// MARK: - INTERNAL TYPES
enum PointOfCareContext: String, CustomStringConvertible {
case premedication, perioperative, postoperative, hospitalised
var description: String {
return self.rawValue.capitalized
}
}
// MARK: - PROPERTIES
var drug: Drug {
get { guard let drug = cd_drug else {
fatalError("Persistent store corrupted: Prescription is missing relationship to Drug.")
}
return drug
}
set { cd_drug = newValue }
}
var timePrescribed: Date {
get { guard let timePrescribed = cd_timePrescribed else {
fatalError("Persistent store corrupted: Prescription is missing timePrescribed.")
}
return timePrescribed
}
set { cd_timePrescribed = newValue }
}
/// When the drug should be administered
/// Passing nil to this property indicates the drug should be given asap (so will return current Date)
var timeScheduled: Date? {
get { guard let timeScheduled = cd_timeScheduled else {
return Date.now
}
return timeScheduled
}
set { cd_timeScheduled = newValue }
}
/// When the drug was administered
/// Nil indicates not given yet
var timeAdministered: Date? {
get { return cd_timeAdministered }
set { cd_timeScheduled = newValue }
}
var doseRate: Measurement<UnitDensity> {
get {
if (cd_doseRate != 0) {
fatalError("Persistent store corrupted: Prescription doseRate == 0.")
}
return Measurement(value: cd_doseRate, unit: .milligramsPerKilogram)
}
set {
cd_doseRate = newValue.converted(to: .milligramsPerKilogram).value
}
}
var dose: Measurement<UnitMass> {
get {
return Measurement(value: cd_dose, unit: .milligrams)
}
set {
cd_doseRate = newValue.converted(to: .milligrams).value
}
}
var doseVolume: Measurement<UnitVolume> {
get {
return Measurement(value: cd_doseVolume, unit: .milliliters)
}
set {
cd_doseVolume = newValue.converted(to: .milliliters).value
}
}
var context: PointOfCareContext {
get {
guard let contextValue = cd_context, let context = PointOfCareContext(rawValue: contextValue) else {
fatalError("Persistent store corrupted: Prescription has an invalid administration context [\(cd_context ?? "")]")
}
return context
}
set {
cd_context = newValue.rawValue
}
}
View Model that is the subject of the test:
extension ProcedurePlanView {
class ViewModel: NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
// swiftlint:disable:next nesting
typealias Dependencies = HasParameterController & HasPersistence & HasViewFactory
private let parameterController: ParameterController
private let persistenceService: PersistenceService
private let viewFactory: ViewFactory
private let frc: NSFetchedResultsController<Prescription>
let patient: Patient
let procedure: Procedure
// MARK: - TabOne conformance
@Published var clinician: String = ""
@Published var anaesthetist: String = ""
@Published var assistant: String = ""
@Published var history: String = ""
@Published var tasks: String = ""
@Published var complications: String = ""
@Published var mucousMembraneColor: MucousMembraneColor?
@Published var asaGrade: ASAGrade?
@Published var cannulaPosition: CannulaPosition?
@Published var cannulaSide: Side?
@Published var cannulaGauge: PeripheralCannulaGauge?
@Published var auscultation: String = ""
@Published var temperament: Double?
@Published var airwayType: AirwayType?
@Published var airwaySize: String?
@Published var airwayCuffStatus: Bool?
@Published var breathingSystem: BreathingSystemType?
@Published var prescriptions: [Prescription]?
// MARK: - INIT
init(procedure: Procedure? = nil, patient: Patient, dependencies: Dependencies) {
self.persistenceService = dependencies.persistenceService
self.parameterController = dependencies.parameterController
self.viewFactory = dependencies.viewFactory
var currentProcedure: Procedure?
if let procedure {
currentProcedure = procedure
} else {
currentProcedure = Procedure(context: persistenceService.viewContext)
currentProcedure!.patient = patient
}
let frc = ProcedurePlanView.ViewModel.createPremedFRCUsing(
patient,
procedure: currentProcedure!,
context: dependencies.persistenceService.viewContext
)
self.frc = frc
self.patient = patient
self.procedure = currentProcedure!
self.prescriptions = ProcedurePlanView.ViewModel.performInitialFetchFor(frc)
super.init()
self.frc.delegate = self
}
// MARK: - PUBLIC METHODS
func makeParameterGridView() -> some View {
viewFactory.makeParameterGridView(patient: patient)
}
func resetForm() {
clinician.removeAll()
anaesthetist.removeAll()
assistant.removeAll()
history.removeAll()
tasks.removeAll()
complications.removeAll()
mucousMembraneColor = nil
asaGrade = nil
cannulaPosition = nil
cannulaSide = nil
cannulaGauge = nil
auscultation.removeAll()
temperament = nil
airwayType = nil
airwaySize = nil
airwayCuffStatus = nil
breathingSystem = nil
}
func save() {
procedure.patient = patient
procedure.clinican = clinician
procedure.anaesthetist = anaesthetist
procedure.assistant = assistant
procedure.history = history
procedure.tasks = tasks
procedure.complications = complications
procedure.asaGrade = asaGrade
Logger.viewModel.warning("Incomplete implementaton of cannula data in Procedure managed object and VM")
_ = Observation.create(
in: persistenceService.viewContext,
patient: patient,
parameter: parameterController.getParameterWith(name: .mucousMembraneColor),
stringValue: mucousMembraneColor?.rawValue ?? "Unknown"
)
do {
try persistenceService.viewContext.saveIfNeeded()
} catch {
fatalError(
"Unable to save context \(persistenceService.viewContext) to store due to error: \(error.localizedDescription)"
)
}
}
// MARK: - PRIVATE METHODS
private static func createPremedFRCUsing(_ patient: Patient, procedure: Procedure, context: NSManagedObjectContext) -> NSFetchedResultsController<Prescription> {
let request = Prescription.fetchRequest()
request.predicate = NSPredicate(format: "procedure == %@", procedure)
request.sortDescriptors = [NSSortDescriptor(keyPath: \Prescription.cd_drug?.cd_nameGeneric, ascending: false)]
let frc = NSFetchedResultsController(
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: nil,
cacheName: nil
)
return frc
}
private static func performInitialFetchFor(_ frc: NSFetchedResultsController<Prescription>) -> [Prescription] {
do {
try frc.performFetch()
} catch {
Logger.persistenceService.critical(
"FRC failed to fetch Drugs from persistent store: \(error.localizedDescription)"
)
}
return frc.fetchedObjects ?? []
}
// MARK: - NSFetchedResultsControllerDelegate conformance
internal func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
let newPrescriptions = controller.fetchedObjects as? [Prescription] ?? []
prescriptions = newPrescriptions
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论