Ich habe zwei Entitäten (Kategorien, Ereignis) und sie haben Zwei-Wege-Viele-zu-viele-Beziehung. Eine Kategorie kann mehr als ein Ereignis haben und ein Ereignis kann mehr als eine Kategorie haben. Die Kategorie-zu-Ereignis-Beziehung ist optional in dem Sinne, dass Kategorie ohne ein Ereignis existieren kann, aber die Beziehung von Ereignis zu Kategorie ist obligatorisch (Ereignis kann nicht ohne Kategorie existieren). Ich versuche, Ereignisse einzufügen und Kategorien hinzuzufügen, aber ich bekomme NSValidationErrorValue = Beziehungsfehler. Dies ist mein Code:Core Data: Problem beim Einfügen von Daten mit Beziehung
private func storeEventsXMLStream(_ xml: XMLIndexer) {
let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.persistentStoreCoordinator
// Remove all data before inserting
// This line of code is necessary because data needs to be downloaded on daily basis.
// Otherwise, I will get redundant data.
removeAllExistingData("Event_Ottawa", managedObjectContext: managedObjectContext)
autoreleasepool { // Scoping is necessary to fix memory leak
for xmlcat in xml["events"]["event"]{
let event = NSEntityDescription.insertNewObject(forEntityName: "Event_Ottawa", into: managedObjectContext) as! Event_Ottawa
event.id = Int32((xmlcat.element?.attribute(by: "id")?.text)!)!
event.website_url_english = xmlcat["website_url_english"].element?.text
event.website_url_french = xmlcat["website_url_french"].element?.text
// setting other attributes of events here. Exactly like I did in above 3 line
// Just another attribute. Storing it a String in Coredata
var recur_rules = ""
for rule in xmlcat["recur_rules"]["recur_rule"] {
recur_rules += (rule.element?.attribute(by: "weekday")?.text)!
}
if !recur_rules.isEmpty {
event.recur_rules = recur_rules
}
do {
var predicateArray:[NSPredicate] = []
// Categories are inserted to the Coredata before this method call. So I'm fetching the applicable one here.
for category in xmlcat["categories"]["category"] {
let predicate = NSPredicate(format: "id = %@", (category.element?.attribute(by: "id")?.text)!)
predicateArray.append(predicate)
}
let requestCategory:NSFetchRequest<Category_Event_Ottawa> = Category_Event_Ottawa.fetchRequest()
requestCategory.predicate = NSCompoundPredicate.init(andPredicateWithSubpredicates: predicateArray)
let managedContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
managedContext.persistentStoreCoordinator = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.persistentStoreCoordinator
let applicableCategories = try managedContext.fetch(requestCategory)
for category in applicableCategories {
event.addToCategory(category)
}
}
} catch {
print(error)
}
}
}
// only save once per batch insert
do {
try managedObjectContext.save()
} catch {
print(error)
}
managedObjectContext.reset() <-- I get EXC_BAD_ACCESS, when I use the same object context for fetching as insertion
}
Und die Fehler, die ich erhalte:
Error Domain=NSCocoaErrorDomain Code=1560 "(null)" UserInfo={NSDetailedErrors=(
"Error Domain=NSCocoaErrorDomain Code=1550 \"The operation couldn\U2019t be completed. (Cocoa error 1550.)\" UserInfo={Dangling reference to an invalid object.=null, NSValidationErrorValue=Relationship 'category' on managed object (0x6100050963f0)
Wenn den gleichen verwaltete Objektkontext sowohl für das Einsetzen und Abrufen verwenden, ich habe nicht diesen Fehler mehr. Aber ich bekomme EXC_BAD_ACCESS von der Zeile, die Kontextobjekt zurückgesetzt. Ich habe es aus einem anderen Beitrag erfahren, dass CoreData nicht Thread-sicher ist. Vielleicht war das ein Problem. Aber wie behebe ich dieses Problem? Falls es relevant ist, ist die Löschregel für die Event-Kategorie-Beziehung Nulify und Category-Event ist Cascade.
Einige Fragen/Kommentare: 1) Wenn Sie Ihrer Datenmodell-Datei eine neue Beziehung hinzufügen, ist die 'Optional' -Eigenschaft standardmäßig aktiviert - Sie haben dies zu einem bestimmten Zeitpunkt nicht deaktiviert? Das wäre der einfachste Grund, warum Sie den Beziehungsfehler bekommen. 2) Ungeachtet des Fehlers, was versuchst du zu tun/zu erwarten, wenn du 'reset()' im Kontext aufruft? – MathewS
3) Ich bin immer noch vertraut mit der 'NSPersistentContainer' Klasse, aber gibt es irgendeinen Grund, dass Sie Kontext auf diese Weise erstellen anstatt' PersistentContainer.viewContext' für den Hauptkontext und 'newBackgroundContext()' um einen Hintergrundkontext zu erstellen wie Beispielcode zeigt? – MathewS
4) Re-Thread-Sicherheit, für jeden Kontext im Hintergrund/private thread, sollten Sie Aktionen innerhalb der Context 'durchführen' (async) oder' performAndWait' (sync) Schließungen, um Thread-bezogene Fehler zu verhindern https: // Entwickler .apple.com/reference/coredata/nsmanagedobjectcontext/1506578-perform – MathewS