在UITableView的一部分上使用NSFetchedResultsController

时间:2016-04-08 05:42:35

标签: ios swift uitableview nsfetchedresultscontroller

我在UITableViewController中有一个UISplitViewController。这个tableViewController收到两件事:

  1. 发票数组
  2. 客户对象
  3. 所以我正在做的是在UITableView的第一部分(或Section 0)填充发票详细信息。

    对于第二部分,我使用NSFetchedResultsController来获取具有invoice == nil的客户的所有属性,并在表格视图的第二部分中显示该属性。

    所以基本上,仅在NSFetchedResultsController的一部分上使用UITableViewController而不是整个事物。

    现在,一切正常。但是当我点击第2部分的行时,我会让用户将property添加到新发票中。当我这样做时,我收到了这个错误:

    CoreData: error: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
    

    不确定为什么会这样。我理解fetchedResultsController期望第0节,但我确保它被手动强制只使用第1节。

    参考代码为:

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        switch (type) {
        case .Insert:
            if let indexPath = newIndexPath {
                let editedNewIndexPath = NSIndexPath(forRow: indexPath.row, inSection: 1)
                tableView.insertRowsAtIndexPaths([editedNewIndexPath], withRowAnimation: .Fade)
            }
            break;
        case .Delete:
            if let indexPath = indexPath {
                let editedCurrentIndexPath = NSIndexPath(forRow: indexPath.row, inSection: 1)
                tableView.deleteRowsAtIndexPaths([editedCurrentIndexPath], withRowAnimation: .Fade)
            }
            break;
        case .Update:
            if let indexPath = indexPath {
                let editedCurrentIndexPath = NSIndexPath(forRow: indexPath.row, inSection: 1)
                if let cell = tableView.cellForRowAtIndexPath(editedCurrentIndexPath){
                    configureCell(cell, atIndexPath: editedCurrentIndexPath)
                    //tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None)
                }
            }
            break;
        case .Move:
            if let indexPath = indexPath {
                let editedCurrentIndexPath = NSIndexPath(forRow: indexPath.row, inSection: 1)
                tableView.deleteRowsAtIndexPaths([editedCurrentIndexPath], withRowAnimation: .Fade)
            }
    
            if let newIndexPath = newIndexPath {
                let editedNewIndexPath = NSIndexPath(forRow: newIndexPath.row, inSection: 1)
                tableView.insertRowsAtIndexPaths([editedNewIndexPath], withRowAnimation: .Fade)
            }
            break;
        }
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 2
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0{
            if let ivData = self.invoices{
                print("Section0 - \(ivData.count)")
                return ivData.count
            }
        }
        else if section == 1{
            if let sections = fetchedResultsController.sections {
                let sectionInfo = sections[0]
                print("Section1 - \(sectionInfo.numberOfObjects)")
                if sectionInfo.numberOfObjects > 0{
                    return sectionInfo.numberOfObjects
                }
                else{
                    return 1
                }
            }
        }
        return 0
    }
    

    保存新发票的代码是:

    do{
                        self.invoices!.append(billRecord as! InvoiceInfo)
                        try billRecord.managedObjectContext?.save()
                        try self.customer!.managedObjectContext?.save()
                        try record.managedObjectContext?.save()
                        //self.lookUpLotsWithoutBills()
                        self.tableView.reloadData()
    
                    }
                    catch{
                        self.invoices!.removeObject(ivRecord)
                        let alertController = UIAlertController(title: "Unexpected Error", message: "Your data could not be updated. Please try again later.", preferredStyle: .Alert)
                        alertController.addAction(UIAlertAction(title: "Done", style: .Cancel, handler: nil))
                        self.presentViewController(alertController, animated: true, completion: nil)
                    }
    

    这里可能有什么问题?

1 个答案:

答案 0 :(得分:0)

看起来你的FRC工作正常,但你的代码并没有告诉表格视图有关新的发票行被添加到第0部分。它不是很清楚为什么,但我&#39 ;我猜它是因为FRC会在您添加发票之后但在您在桌面上调用重新加载数据之前触发更新。在那个时间点,第0部分的行数是错误的,你还没有告诉它有关它的信息。