在我的应用中,当operation.recordChangedBlock {}
内的func fetchZoneChanges(database: CKDatabase, databaseTokenKey: String, zoneIDs: [CKRecordZoneID], completion: @escaping () -> Void)
完成后,我使用从CloudKit收到的新名称值更新Core Data数据库中的coreData记录。
当我试图保存上下文时,出现错误尝试以递归方式调用-save:on on context aborted 。
func updateCoreDataRecord(editedRecord: Record, newName: String, handleComplete_RecordEditedInCoreData:(()->())) {
let record_RecordID = editedRecord.recordID!
let request: NSFetchRequest<Record> = Record.fetchRequest()
request.predicate = NSPredicate(format: "recordID = %@", record_RecordID)
do {
let results = try self.viewContext?.fetch(request)
if results?.count == 1 {
let recordToUpdate = results![0]
recordToUpdate.setValue(newName, forKey: "name")
DispatchQueue.main.async { // Here I receive the error when editing goes from CloudKit
self.saveViewContext()
}
handleComplete_RecordEditedInCoreData()
}
} catch {
print(error)
}
}
以下是其他相关功能:
func saveViewContext() {
let context = self.getViewContext()
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func getViewContext() -> NSManagedObjectContext {
return self.persistentContainer.viewContext
}
我的应用中的所有viewContext
次调用都是在主线程中进行的。我想这可能会导致错误。
错误导致saveViewContext
方法。我不确定,但我认为这可能是一个并发问题,但我不知道如何解决它。
在获取CloudKit Record更新时,如何重写代码以避免此错误?我已经尝试将所有调用包装在主队列上运行,但这并没有帮助。
当用户更改设备上的核心数据记录时,我也使用相同的updateCoreDataRecord()
方法,这不会导致错误。我只是在从operation.recordChangedBlock {}中的CloudKit接收记录更改时才收到此错误,我在其中为记录进行Core Data更新。
答案 0 :(得分:0)
这个方法是在主线程上触发的吗?如果没有,您需要将所有Core Data工作移动到主线程,如果您正在对viewContext进行操作,而不仅仅是保存。
答案 1 :(得分:0)
我知道这是一个老问题,但我刚才遇到了这个问题。就我而言,我有一个NSFetchedResultsController
来监听对数据存储的更改(它在保存时触发)。该控制器将一些同步事件置于运动中,这需要获取一些NSManagedObject
,然后调用.save()
以准备随后调用.refresh(_:mergeChanges:)
。所有这些似乎都与原始.save()
调用在同一运行循环中。
尽管是间接的,但我是递归地调用.save()
!不知何故,我的应用程序像这样平稳运行了一段时间,但是我刚刚遇到了一个循环出现的情况。我通过在核心数据包装器的save()
方法中添加一个ivar和一个检查项来对其进行修复,该方法可以跟踪它是否当前处于保存操作中(还与.performAndWait(_:)
结合使用),并返回是否存在。 / p>
无论这个叙述对您有没有帮助,我希望它至少在以后再次出现此问题时对我自己和Google员工有用!
答案 2 :(得分:0)
我也陷入了这个错误。错误产生的Stacktrace以及当时运行的所有线程的完整stacktrace都没有太大帮助。
如果通过了coredata并发调试参数,则可以立即发现问题:
-com.apple.CoreData.ConcurrencyDebug 1
在我的情况下,原因是:在某个后台线程上,我正在访问与另一个线程绑定的数据库。我一改正错误的线程用法,问题就解决了。