【问题标题】:Updating sections with NSFetchedResultsController使用 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
    }
}

这会导致与上面发布的相同的错误。关于为什么永远不会调用它的任何想法?

【问题讨论】:

    标签: ios swift core-data nsfetchedresultscontroller


    【解决方案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)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多