我有兩個實體(類別,事件),他們有雙向多對多關係。一個類別可以有多個事件,一個事件可以有多個類別。類別到事件的關係是可選的,因爲類別可以在沒有事件的情況下存在,但事件到類別的關係是強制性的(事件不能在沒有類別的情況下存在)。我試圖插入事件並添加類別給他們,但我得到NSValidationErrorValue =關係錯誤。這是我的代碼:核心數據:問題插入數據與關係
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
}
我收到的錯誤:
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)
如果使用插入和取出相同的管理對象方面,我沒有得到這個錯誤了。但是我從重置上下文對象的行中獲取EXC_BAD_ACCESS。我從另一篇文章中瞭解到CoreData不是線程安全的。所以也許這是一個問題。但我該如何解決這個問題?如果相關,則事件類別關係的刪除規則爲Nullify,而類別事件爲級聯。
一些問題/評論:1)當你添加一個新的關係到你的數據模型文件時,'Optional'屬性默認被選中 - 你沒有取消選中這個點?這將是你得到關係錯誤的最簡單的原因。 2)不管錯誤如何,當你在上下文中調用reset()時,你試圖做什麼/期望發生什麼? – MathewS
3)我仍然熟悉使用'NSPersistentContainer'類,但是有沒有什麼原因可以用這種方式創建上下文,而不是使用'PersistentContainer.viewContext'作爲主上下文,'newBackgroundContext()'創建背景上下文喜歡示例代碼顯示? – MathewS
4)線程安全,對於在後臺/專用線程中工作的任何上下文,您應該在上下文的'perform'(async)或'performAndWait'(sync)閉包中執行動作,以防止線程相關的錯誤。https:// developer .apple.com/reference/coredata/nsmanagedobjectcontext/1506578-perform – MathewS