使用 NSFetchedResultsController 更新部分
Posted
技术标签:
【中文标题】使用 NSFetchedResultsController 更新部分【英文标题】:Updating sections with NSFetchedResultsController 【发布时间】:2016-09-18 22:35:07 【问题描述】:我有一个名为 ToDoItem
的实体。其中具有三个属性:
@NSManaged var toDoString: String?
@NSManaged var creationDate: NSDate?
@NSManaged var isComplete: NSNumber?
我正在尝试创建一个NSFetchedResultsController
,它将根据isComplete
变量显示两个部分。我能够做到这一点成功购买这样做:
lazy var fetchedResultsController: NSFetchedResultsController =
let questionAnswerFetchRequest = NSFetchRequest(entityName: "ToDoItem")
let questionAnswerFetchSortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
questionAnswerFetchRequest.sortDescriptors = [questionAnswerFetchSortDescriptor]
let frc = NSFetchedResultsController(
fetchRequest: questionAnswerFetchRequest,
managedObjectContext: (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext,
sectionNameKeyPath:"isComplete",
cacheName: nil)
frc.delegate = self
return frc
()
我也实现了这样的删除方法:
//
// MARK: Fetched Results Controller Delegate Methods
//
func controllerWillChangeContent(controller: NSFetchedResultsController)
tableView.beginUpdates()
func controllerDidChangeContent(controller: NSFetchedResultsController)
tableView.endUpdates()
func controller(controller: NSFetchedResultsController,
didChange sectionInfo: NSFetchedResultsSectionInfo,
atSectionIndex sectionIndex: Int,
for type: NSFetchedResultsChangeType)
switch (type)
case .Insert:
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
break
case .Delete:
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
break
default:
break
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?)
switch (type)
case .Insert:
if let indexPath = newIndexPath
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
break;
case .Delete:
if let indexPath = indexPath
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
break;
case .Update:
if let indexPath = indexPath
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
break;
case .Move:
if let indexPath = indexPath
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
if let newIndexPath = newIndexPath
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
break;
问题是当我更新isComplete
属性时,我得到了这个错误:
CoreData:错误:严重的应用程序错误。捕获到异常 在调用期间从 NSFetchedResultsController 的委托 -controllerDidChangeContent:。无效更新:无效的节数。之后表格视图中包含的节数 更新 (1) 必须等于包含在 更新前的表视图(0),加减数 插入或删除的部分(0 插入,0 删除)。与用户信息 (空)
我理解 what 这是在说什么,我只是不明白 为什么 它会导致该错误。我已经按照文档实现了委托方法.....
我已经更新了我的 NSFetchedResultsController
创建,以按照 @wain 的回答添加另一个 sortDescriptor,如下所示:
lazy var fetchedResultsController: NSFetchedResultsController =
let questionAnswerFetchRequest = NSFetchRequest(entityName: "ToDoItem")
let isCompleteSortDescriptor = NSSortDescriptor(key: "isComplete", ascending: false)
let creationDateSortDescriptor = NSSortDescriptor(key: "creationDate", ascending: false)
questionAnswerFetchRequest.sortDescriptors = [isCompleteSortDescriptor, creationDateSortDescriptor]
let frc = NSFetchedResultsController(
fetchRequest: questionAnswerFetchRequest,
managedObjectContext: (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext,
sectionNameKeyPath:"isComplete",
cacheName: nil)
frc.delegate = self
return frc
()
我添加了一些断点,结果发现这个委托方法永远不会被调用:
func controller(controller: NSFetchedResultsController,
didChange sectionInfo: NSFetchedResultsSectionInfo,
atSectionIndex sectionIndex: Int,
for type: NSFetchedResultsChangeType)
switch (type)
case .Insert:
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
break
case .Delete:
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
break
default:
break
这会导致与上面发布的相同的错误。关于为什么永远不会调用它的任何想法?
【问题讨论】:
【参考方案1】:您需要为isComplete
添加一个排序描述符。它应该是第一个排序描述符,然后是你的日期。
基本上,排序和部分需要兼容,而您的当前不兼容。
【讨论】:
您还应该准确检查您获得的委托回调,因为您应该被告知该部分的更新和添加,因此您可能会对视图进行误导性更新,复合更改是难以进行精细管理 我已经更新了任何问题。添加其他排序描述符不起作用:( 您使用的是哪个版本的 swift?看起来func签名应该是func controller(_ controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType)
啊!你是对的!我从这里复制了 func 签名:developer.apple.com/reference/coredata/… 这与您发布的不同。不确定这是否是文档中的印刷错误。 (目前正在运行 swift 2)以上是关于使用 NSFetchedResultsController 更新部分的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 3 中难以配置 NSFetchedResultsController