ios – 核心数据,在实体上设置关系会导致获取结果控制器委托回调中的错误

ios – 核心数据,在实体上设置关系会导致获取结果控制器委托回调中的错误,第1张

概述(实体名称已更改,以便更容易阅读) 环境:Xcode 7 beta 4. iOS 9.0是Base SDK,部署目标是iOS 8.0.在运行iOS 8.4的iPhone 5s真实设备上进行调试. 这是一个有趣的核心数据错误,我花了最近几天调试/尝试理解. – 我已经建立了一个实体RecipeEntity,它具有一些属性和与实体IngredientEntity的多对多关系来表示它的成分. Ingre (实体名称已更改,以便更容易阅读)

环境:Xcode 7 beta 4. iOS 9.0是Base SDK,部署目标是iOS 8.0.在运行iOS 8.4的iPhone 5s真实设备上进行调试.

这是一个有趣的核心数据错误,我花了最近几天调试/尝试理解.

我已经建立了一个实体RecipeEntity,它具有一些属性和与实体IngredIEntEntity的多对多关系来表示它的成分. IngredIEntsEntity与RecipeEntity具有对应的反向关系,两个实体都在关系上设置了以下属性:

有一个视图控制器,它有一个显示成分的表视图,并使用NSFetchedResultsController获取单元格的数据,NSFetchedResultsControllerDelegate设置为视图控制器本身.

以下是用于获取结果控制器委托的原始代码:

// MARK: - FetchedResultsController Delegate/*We're using a nifty solution to fix the issue of multiple Core Data changes occuring at the same time.See here for an explanation of why and how it works:http://www.fruitstandsoftware.com/blog/2013/02/19/uitablevIEw-and-nsfetchedresultscontroller-updates-done-right/*/private var deletedSectionIndexes = NSMutableIndexSet()private var insertedSectionIndexes = NSMutableIndexSet()private var deletedRowIndexPaths = [NSIndexPath]()private var insertedRowIndexPaths = [NSIndexPath]()private var updatedRowIndexPaths = [NSIndexPath]()func controller(controller: NSFetchedResultsController,dIDChangeObject anObject: NSManagedobject,atIndexPath indexPath: NSIndexPath?,forChangeType type: NSFetchedResultsChangeType,newIndexPath: NSIndexPath?) {    switch type {    case NSFetchedResultsChangeType.Insert:        if let newIndexPath = newIndexPath {            if insertedSectionIndexes.containsIndex(newIndexPath.section) {                // If we've already been told that we're adding a section for this inserted row we skip it since it will handled by the section insertion.                return            }            insertedRowIndexPaths.append(newIndexPath)        }    case NSFetchedResultsChangeType.Delete:        if let indexPath = indexPath {            if deletedSectionIndexes.containsIndex(indexPath.section) {                // If we've already been told that we're deleting a section for this deleted row we skip it since it will handled by the section deletion.                return            }            deletedRowIndexPaths.append(indexPath)        }    case NSFetchedResultsChangeType.Move:        if let newIndexPath = newIndexPath {            if !insertedSectionIndexes.containsIndex(newIndexPath.section) {                insertedRowIndexPaths.append(newIndexPath)            }        }        if let indexPath = indexPath {            if !deletedSectionIndexes.containsIndex(indexPath.section) {                deletedRowIndexPaths.append(indexPath)            }        }    case NSFetchedResultsChangeType.Update:        if let indexPath = indexPath {            updatedRowIndexPaths.append(indexPath)        }    }}func controller(controller: NSFetchedResultsController,dIDChangeSection sectionInfo: NSFetchedResultsSectionInfo,atIndex sectionIndex: Int,forChangeType type: NSFetchedResultsChangeType) {    switch type {    case NSFetchedResultsChangeType.Insert:        insertedSectionIndexes.addindex(sectionIndex)    case NSFetchedResultsChangeType.Delete:        deletedSectionIndexes.addindex(sectionIndex)    default:        break    }}func controllerDIDChangeContent(controller: NSFetchedResultsController) {    tableVIEw.beginUpdates()    tableVIEw.deleteSections(deletedSectionIndexes,withRowAnimation: UItableVIEwRowAnimation.automatic)    tableVIEw.insertSections(insertedSectionIndexes,withRowAnimation: UItableVIEwRowAnimation.automatic)    tableVIEw.deleteRowsAtIndexPaths(deletedRowIndexPaths,withRowAnimation: UItableVIEwRowAnimation.left)    tableVIEw.insertRowsAtIndexPaths(insertedRowIndexPaths,withRowAnimation: UItableVIEwRowAnimation.Right)    tableVIEw.reloadRowsAtIndexPaths(updatedRowIndexPaths,withRowAnimation: UItableVIEwRowAnimation.automatic)    tableVIEw.endUpdates()    // Clear the collections so they are ready for their next use.    insertedSectionIndexes = NSMutableIndexSet()    deletedSectionIndexes = NSMutableIndexSet()    deletedRowIndexPaths = [NSIndexPath]()    insertedRowIndexPaths = [NSIndexPath]()    updatedRowIndexPaths = [NSIndexPath]()}

问题是当设置RecipeEntity与之关系的IngredIEntEntity时,会发生以下故障:

2015-08-12 14:43:34.777 MyApp[9707:2866157] *** Assertion failure in -[MyApp.MyApptableVIEw _endCellAnimationsWithContext:],/SourceCache/UIKit/UIKit-3347.44.2/UItableVIEw.m:1222
2015-08-12 14:43:34.782 MyApp[9707:2866157] CoreData: error: SerIoUs application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDIDChangeContent:. attempt to delete and reload the same index path ( {length = 2,path = 0 – 0}) with userInfo (null)

我最终将其跟踪到控制器:dIDChangeObject:atIndexPath:forChangeType:newIndexPath:使用更改类型NSFetchedResultsChangeType.Move调用,但indexPath和newIndexPath都使用相同的NSIndexPath.

这里大致是将实体添加为关系的代码:

// setofIngredIEnts is an NSSet of IngredIEntEntity's retreived from Core Data.recipeEntity.ingredIEnts = setofIngredIEnts

将此switch case语句(在控制器中:dIDChangeObject:atIndexPath:forChangeType:newIndexPath:delegate方法)更改为以下内容可解决此问题:

case NSFetchedResultsChangeType.Move:        // If the indexPath and the newIndexPath are the same,then they shouldn't really be deleted and inserted,the row should just be reloaded,// otherwise it causes a crash.        if indexPath != newIndexPath {            if let newIndexPath = newIndexPath {                if !insertedSectionIndexes.containsIndex(newIndexPath.section) {                    insertedRowIndexPaths.append(newIndexPath)                }            }            if let indexPath = indexPath {                if !deletedSectionIndexes.containsIndex(indexPath.section) {                    deletedRowIndexPaths.append(indexPath)                }            }        } else if let indexPath = indexPath {            updatedRowIndexPaths.append(indexPath)        }

主要问题:

那么为什么要在Core Data实体对象上设置关系的值会导致控制器:dIDChangeObject:atIndexPath:forChangeType:newIndexPath:用更改类型调用.移动但是相同的新旧索引路径?

这是Xcode 7 beta 4 / Swift 2.0中的错误还是我做错了什么?

我真的很想知道这里发生了什么,我花了几天时间尝试调试,所以感谢你的帮助!

让我知道,如果有任何更多的信息,我可以提供,这将是有益的,谢谢.

解决方法 我想知道这是否是因为.当对象的已更改属性是获取请求中使用的排序描述符之一时,会报告移动更改.

我看到indexPath和newIndexPath也经常相同.根据文档,这被认为也是隐式更新.

来自NSFetchedResultsController.h

The Move object is reported when the changed attribute on the object is one of the sort descriptors used in the fetch request. An update of the object is assumed in this case,but no separate update message is sent to the delegate.
总结

以上是内存溢出为你收集整理的ios – 核心数据,在实体上设置关系会导致获取结果控制器委托回调中的错误全部内容,希望文章能够帮你解决ios – 核心数据,在实体上设置关系会导致获取结果控制器委托回调中的错误所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1004407.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存