我正在尝试将核心数据中的验证设置为简单的托管对象结构。
两者之间存在Building
和Floor
,并且两者之间是一对多的关系(在建筑物上有很多楼层)。
Floor
中的验证器看起来像这样
// extension of auto generated managed object (Floor)
extension Floor {
override public func validateForInsert() throws {
try super.validateForInsert()
if (self.building == nil) {
throw ValidationError.missingBuilding("a floor requires a building")
}
}
}
还有我简单的测试经理:
import Foundation
import CoreData
class ObjectNodeManager {
let persistentContainer: NSPersistentContainer!
init(container: NSPersistentContainer) {
self.persistentContainer = container
self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
}
lazy var backgroundContext: NSManagedObjectContext = {
return self.persistentContainer.newBackgroundContext()
}()
func insertObjectNode(objectNode: ObjectNode) -> ObjectNode? {
backgroundContext.insert(objectNode)
return objectNode
}
func save() {
if backgroundContext.hasChanges {
do {
try backgroundContext.save()
} catch {
fatalError("save error \(error)")
}
}
}
}
当我尝试创建新建筑物和地板的保存时,出现异常。
let building = Building(context: manager.backgroundContext)
let floor = Floor(context: manager.backgroundContext)
floor.building = building // VALIDATION EXCEPTION!
// a basic backgroundContext.save() (persistentContainer) in the manager
manager.save()
对于validationForInsert
,我无法插入/保存托管对象。另外,我可以使用validationForUpdate
,但是为时已晚,因为我不想存储没有与Floor
有适当关系的Building
。
有人建议如何保存具有所需关系并在插入时进行验证的管理对象?
谢谢。
答案 0 :(得分:1)
manager.background
上下文始终返回新的上下文,您的building
和floor
存在于两个不同的上下文中。
let backgroundContext = manager.backgroundContext
let building = Building(context: backgroundContext)
let floor = Floor(context: backgroundContext)
floor.building = building
manager.save()
答案 1 :(得分:0)
当我于2009年首次开始使用Core Data时,遇到了类似的错误警报问题。我的解决方案过去是,现在仍然是:不要在顶级 main 受管对象上下文中使用Core Data的验证。也就是说,不要实现validateForInsert()
。如您所见,即使Core Data确实正确地标记了 true 警报,它也会在保存期间发生,为时已晚,无法对其进行任何智能处理。当用户无法保存其工作时,他们会感到不满意。
您可能希望在 child 受管对象上下文中使用Core Data的验证。在这种情况下,您通常位于视图控制器中,在用户输入验证错误后立即捕获该验证错误,并且您对错误的立即表示对用户来说很有意义。