iOS Swift 3核心数据-致命错误尝试递归调用-保存:在上下文中中止
我需要一些帮助来调试我在对核心数据进行大约150次调用以保存上下文时遇到的错误。在确定是否需要更新核心数据记录,因为它不存在,或者CloudKit记录更为新之后,我为每个异步调用保存核心数据上下文,但每次调用只调用一次save。我能得到一些帮助来理解递归在哪里发生吗iOS Swift 3核心数据-致命错误尝试递归调用-保存:在上下文中中止,ios,core-data,swift3,Ios,Core Data,Swift3,我需要一些帮助来调试我在对核心数据进行大约150次调用以保存上下文时遇到的错误。在确定是否需要更新核心数据记录,因为它不存在,或者CloudKit记录更为新之后,我为每个异步调用保存核心数据上下文,但每次调用只调用一次save。我能得到一些帮助来理解递归在哪里发生吗 2017-06-17 12:13:51.295312-0400 My Toy Chest[2161:2177589] fatal error: Unresolved error Error Domain=NSCocoaErrorDo
2017-06-17 12:13:51.295312-0400 My Toy Chest[2161:2177589] fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=132001 "(null)" UserInfo={message=attempt to recursively call -save: on the context aborted, stack trace=(
0 CoreData 0x0000000188e8802c <redacted> + 164
1 My Toy Chest 0x0000000100109e0c _TFC12My_Toy_Chest11AppDelegate11saveContextfT_T_ + 172
2 My Toy Chest 0x00000001000de61c _TFFFC12My_Toy_Chest21ActionFigureSpecifics24setActionFigureSpecificsFT_T_U_FTGSqCSo8CKRecord_GSqPs5Error___T_U0_FT_T_ + 8464
3 My Toy Chest 0x00000001000946d4 _TTRXFo___XFdCb___ + 44
4 libdispatch.dylib 0x0000000101549a50 _dispatch_call_block_and_release + 24
5 libdispatch.dylib 0x0000000101549a10 _dispatch_client_callout + 16
6 libdispatch.dylib 0x000000010154eb78 _dispatch_main_queue_callback_4CF + 1204
7 CoreFoundation 0x0000000186b3d0c8 <redacted> + 12
8 CoreFoundation 0x0000000186b3ace4 <redacted> + 1572
9 CoreFoundation 0x0000000186a6ada4 CFRunLoopRunSpecific + 424
10 GraphicsServices 0x00000001884d4074 GSEventRunModal + 100
11 UIKit 0x000000018cd25058 UIApplicationMain + 208
12 My Toy Chest 0x000000010010a668 main + 76
13 libdyld.dylib 0x0000000185a7959c <redacted> + 4
)}, [AnyHashable("stack trace"): <_NSCallStackArray 0x17464c1b0>(
0 CoreData 0x0000000188e8802c <redacted> + 164,
1 My Toy Chest 0x0000000100109e0c _TFC12My_Toy_Chest11AppDelegate11saveContextfT_T_ + 172,
2 My Toy Chest 0x00000001000de61c _TFFFC12My_Toy_Chest21ActionFigureSpecifics24setActionFigureSpecificsFT_T_U_FTGSqCSo8CKRecord_GSqPs5Error___T_U0_FT_T_ + 8464,
3 My Toy Chest 0x00000001000946d4 _TTRXFo___XFdCb___ + 44,
4 libdispatch.dylib 0x0000000101549a50 _dispatch_call_block_and_release + 24,
5 libdispatch.dylib 0x0000000101549a10 _dispatch_client_callout + 16,
6 libdispatch.dylib 0x000000010154eb78 _dispatch_main_queue_callback_4CF + 1204,
7 CoreFoundation 0x0000000186b3d0c8 <redacted> + 12,
8 CoreFoundation 0x0000000186b3ace4 <redacted> + 1572,
9 CoreFoundation 0x0000000186a6ada4 CFRunLoopRunSpecific + 424,
10 GraphicsServices 0x00000001884d4074 GSEventRunModal + 100,
11 UIKit 0x000000018cd25058 UIApplicationMain + 208,
12 My Toy Chest 0x000000010010a668 main + 76,
13 libdyld.dylib 0x0000000185a7959c <redacted> + 4
)
, AnyHashable("message"): attempt to recursively call -save: on the context aborted]: file /Users/jasongloor/Documents/Development/My Toy Chest/My Toy Chest/AppDelegate.swift, line 211
2017-06-17 12:13:51.295312-0400我的玩具箱[2161:2177589]致命错误:未解决的错误域=NSCocoaErrorDomain code=132001“(null)”UserInfo={message=尝试递归调用-保存:在上下文中中止,堆栈跟踪=(
0核心数据0x0000000188e8802c+164
1我的玩具箱0x0000000100109e0c\u TFC12My\u玩具箱11AppDelegate11SaveContextFT\u T\u172
2我的玩具箱0x00000001000de61c\U TFFFC12My\U玩具箱21动作图形规格24设置动作图形规格SFT\U T\U FTGSqCSo8CKRecord\U gsqps5错误\U\U T\U T\U+8464
我的玩具箱0x00000001000946d4
4 libdispatch.dylib 0x0000000101549a50 \u调度\u调用\u块\u和\u释放+24
5 libdispatch.dylib 0x0000000101549a10 _dispatch_client_callout+16
6 libdispatch.dylib 0x000000010154eb78_dispatch_main_queue_callback_4CF+1204
7 CoreFoundation 0x0000000186b3d0c8+12
8核心基金会0x0000000186b3ace4+1572
9 CoreFoundation 0x0000000186a6ada4 CFRunLoopRunSpecific+424
10个图形服务0x00000001884d4074 GSEventRunModal+100
11 UIKit 0x000000018cd25058 UIApplicationMain+208
12我的玩具箱0x000000010A668主+76
13 libdyld.dylib 0x0000000185a7959c+4
)},[AnyHashable(“堆栈跟踪”):(
0 CoreData 0x0000000188e8802c+164,
1我的玩具箱0x0000000100109e0c\u TFC12My\u玩具箱11AppDelegate11SaveContextft\u T\u172,
2我的玩具箱0x00000001000de61c\U TFFFC12My\U玩具箱21动作图形规格24设置动作图形规格SFT\U T\U FTGSqCSo8CKRecord\U gsqps5错误\U\U T\U T\U+8464,
我的玩具箱0x00000001000946d4,
4 libdispatch.dylib 0x0000000101549a50 \u调度\u调用\u块\u和\u释放+24,
5 libdispatch.dylib 0x0000000101549a10 _dispatch_client_callout+16,
6 libdispatch.dylib 0x000000010154eb78_dispatch_main_queue_callback_4CF+1204,
7 CoreFoundation 0x0000000186b3d0c8+12,
8核心基金会0x0000000186b3ace4+1572,
9 CoreFoundation 0x0000000186a6ada4 CFRunLoopRunSpecific+424,
10个图形服务0x00000001884d4074 GSEventRunModal+100,
11 UIKit 0x000000018cd25058 UIApplicationMain+208,
12我的玩具箱0x000000010A668主+76,
13 libdyld.dylib 0x0000000185a7959c+4
)
,AnyHashable(“message”):尝试递归调用-save:在上下文中中止]:file/Users/jasongloor/Documents/Development/My Toy cost/My Toy cost/AppDelegate.swift,第211行
导致坠机的代码。下面的代码对于数组中的每个动作图形调用一次
func setActionFigureSpecifics() {
// check for specifics already set to prevent multiple calls
if isActionFigureSpecificSetFromICloud {
self.delegate?.updateActionFigureSpecificsModel()
}
else {
//////////
// Core Date Fetch Request
//////////
let isNewCoreDataRecord = setCoreDataActionFigureSpecifics()
//////////
// iCloud fetch request
//////////
if SharedData.sharedInstance.isUserPreferenceToUseICloud == true {
isActionFigureSpecificSetFromICloud = true
// Private Database
let privateDatabase = SharedData.sharedInstance.privateDatabase
let actionFigureSpecificsRecordId = CKRecordID(recordName: actionFigureSpecificsGlobalUniqueId)
privateDatabase!.fetch(withRecordID: actionFigureSpecificsRecordId){ [unowned self] record, error in
var ckError: CKError?
if let cloudKitError = error as? CKError {
ckError = cloudKitError
}
if (ckError != nil && (ckError?.code != CKError.Code.unknownItem)) {
}
else {
if record != nil { // check for records found
self.actionFigureSpecificsRecord = record
let iCloudUpdateDate = self.actionFigureSpecificsRecord!.object(forKey: kUpdateDate) as! Date
// set the core data record from the cloud if the record is new
if isNewCoreDataRecord == true {
self.actionFigureSpecificsCoreData!.haveTheFigure = self.actionFigureSpecificsRecord!.object(forKey: kHaveTheFigure) as! Bool
self.actionFigureSpecificsCoreData!.haveFigureCount = self.actionFigureSpecificsRecord!.object(forKey: kHaveFigureCount) as! Int64
self.actionFigureSpecificsCoreData!.wantTheFigure = self.actionFigureSpecificsRecord!.object(forKey: kWantTheFigure) as! Bool
self.actionFigureSpecificsCoreData!.wantFigureCount = self.actionFigureSpecificsRecord!.object(forKey: kWantFigureCount) as! Int64
self.actionFigureSpecificsCoreData!.updateDate = iCloudUpdateDate as NSDate
SharedData.sharedInstance.appDelegate.saveContext()
}
let coreDataUpdateDate = self.actionFigureSpecificsCoreData!.updateDate! as Date
// determine which data is more current by date
if coreDataUpdateDate < iCloudUpdateDate { // reset core data
self.actionFigureSpecificsCoreData!.haveTheFigure = self.actionFigureSpecificsRecord!.object(forKey: kHaveTheFigure) as! Bool
self.actionFigureSpecificsCoreData!.haveFigureCount = self.actionFigureSpecificsRecord!.object(forKey: kHaveFigureCount) as! Int64
self.actionFigureSpecificsCoreData!.wantTheFigure = self.actionFigureSpecificsRecord!.object(forKey: kWantTheFigure) as! Bool
self.actionFigureSpecificsCoreData!.wantFigureCount = self.actionFigureSpecificsRecord!.object(forKey: kWantFigureCount) as! Int64
self.actionFigureSpecificsCoreData!.updateDate = iCloudUpdateDate as NSDate
// Recursion Error occurs here
// Recursion Error occurs here
SharedData.sharedInstance.appDelegate.saveContext()
}
else if coreDataUpdateDate > iCloudUpdateDate { // reset iCloud data
self.actionFigureSpecificsRecord!.setObject(self.actionFigureSpecificsCoreData!.haveTheFigure as CKRecordValue?, forKey: kHaveTheFigure)
self.actionFigureSpecificsRecord!.setObject(self.actionFigureSpecificsCoreData!.haveFigureCount as CKRecordValue?, forKey: kHaveFigureCount)
self.actionFigureSpecificsRecord!.setObject(self.actionFigureSpecificsCoreData!.wantTheFigure as CKRecordValue?, forKey: kWantTheFigure)
self.actionFigureSpecificsRecord!.setObject(self.actionFigureSpecificsCoreData!.wantFigureCount as CKRecordValue?, forKey: kWantFigureCount)
self.actionFigureSpecificsRecord!.setObject(self.actionFigureSpecificsCoreData!.updateDate as CKRecordValue?, forKey: kUpdateDate)
#if DEBUG
print("Specifics reset iCloud data: \(String(describing: self.actionFigureSpecificsCoreData!.actionFigureRecordName)) coreData \(coreDataUpdateDate) and iCloud \(iCloudUpdateDate)")
#endif
self.saveActionFigureSpecifics(forUpdateDate: self.actionFigureSpecificsCoreData!.updateDate!)
}
self.delegate?.updateActionFigureSpecificsModel()
}
else {
if self.isActionFigureSpecificsCoreDataDefaultValues() == false {
self.saveActionFigureSpecifics(forUpdateDate: self.actionFigureSpecificsCoreData!.updateDate!)
}
self.delegate?.updateActionFigureSpecificsModel()
}
}
}
}
}
}
func saveContext () {
let context = persistentContainer.viewContext
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 setActionFigureSpecifics(){
//检查已设置的防止多次呼叫的详细信息
如果isActionFigureSpecificSetFromICloud{
self.delegate?.updateActionFigureSpecificsModel()
}
否则{
//////////
//核心日期提取请求
//////////
让isNewCoreDataRecord=setCoreDataActionFigureSpecifics()
//////////
//iCloud获取请求
//////////
如果SharedData.sharedInstance.IsUserPreferenceToSeCloud==true{
IsActionFigureSpecificationSetFromicCloud=true
//专用数据库
让privateDatabase=SharedData.sharedInstance.privateDatabase
让actionFigureSpecificsRecordId=CKRecordID(记录名称:actionFigureSpecificsGlobalUniqueId)
privateDatabase!.fetch(withRecordID:ActionFigurespecificsRecorded){[unowned self]记录,错误在
卡尔:卡尔?
如果让cloudKitError=错误为?CKError{
ckError=cloudKitError
}
if(ckError!=nil&(ckError?.code!=ckError.code.unknownItem)){
}
否则{
if record!=nil{//检查找到的记录
self.actionFigureSpecificsRecord=记录
让iCloudUpdateDate=self.actionFigureSpecificsRecord!。对象(forKey:kUpdateDate)作为!日期
//如果记录是新的,则从云中设置核心数据记录
如果isNewCoreDataRecord==true{
self.actionFigureSpecificsCoreData!.haveTheFigure=self.actionfigurespecicsrecord!。对象(forKey:kHaveTheFigure)为!Bool
self.actionFigureSpecificsCoreData!.haveFigureCount=self.actionFigureSpecificsRecord!。对象(forKey:kavefigureCount)为!Int64
self.actionFigureSpecificsCoreData!.wantTheFigure=self.actionfigurespecicsrecord!。对象(forKey:kWantTheFigure)为!Bool
self.actionFigureSpecificsCoreData!.wantFigureCount=self.actionFigureSpecificsRecord!。对象(forKey:kWantFigureCount)为!Int64
self.actionFigureSpecificsCoreData!.updateDate=iCloudUpdateDate作为NSDate
SharedData.sharedIns
func setCoreDataActionFigureSpecifics() -> Bool {
var isNewCoreDataRecord = false
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "ActionFigureSpecificsCoreData")
// Add Predicate
let predicate = NSPredicate(format: "%K = %@", "actionFigureRecordName", actionFigureGlobalUniqueId)
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate])
do {
let recordArray = try SharedData.sharedInstance.managedObjectContext.fetch(fetchRequest) as! [ActionFigureSpecificsCoreData]
// check for records
if recordArray.count == 0 {
isNewCoreDataRecord = true
actionFigureSpecificsCoreData = ActionFigureSpecificsCoreData(context: SharedData.sharedInstance.managedObjectContext)
actionFigureSpecificsCoreData!.actionFigureRecordName = actionFigureGlobalUniqueId
// want it and have it are set to defaults by core data
actionFigureSpecificsCoreData!.updateDate = NSDate()
SharedData.sharedInstance.appDelegate.saveContext()
}
else if recordArray.count == 1 {
for record in recordArray {
actionFigureSpecificsCoreData = record
...
delegate?.updateActionFigureSpecificsModel()
}
}
else {
print("Multiple action figure specific records fetched for \(actionFigureGlobalUniqueId)")
abort()
}
} catch {
let saveError = error as NSError
print("\(saveError), \(saveError.userInfo)")
}
return isNewCoreDataRecord
}