【问题标题】:Two NSFetchResultControllers , One TableViewController两个 NSFetchResultControllers ,一个 TableViewController
【发布时间】:2015-06-26 12:53:21
【问题描述】:

我想创建一个包含两个部分的 tableView。每个部分将由不同的 NSFetchResultController 填充。我的数据库中有一个名为“newsItem”的实体。在第一部分中,我想显示前五个 newsItems,其中一个名为“main_article”的属性等于 true。第二部分将是所有 newsItems

这是我的 NSFetchResultControllers

 private lazy var fetchedResultsController: NSFetchedResultsController? = { [unowned self] in
    let fetchRequest = NSFetchRequest(entityName: "NewsItem")
    let context = self.managedObjectContext
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
    fetchRequest.predicate = NSPredicate(format: "main_article = YES")
    fetchRequest.fetchLimit = 5
    let controller = NSFetchedResultsController(fetchRequest: fetchRequest,managedObjectContext: context,sectionNameKeyPath: nil,cacheName: nil)

    controller.delegate = self
    controller.performFetch(nil)

    return controller
}()



private lazy var newsroomFetchedResultsController: NSFetchedResultsController? = { [unowned self] in
    let fetchRequest = NSFetchRequest(entityName: "NewsItem")
    let context = self.managedObjectContext
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
    fetchRequest.fetchBatchSize = 100
    let controller = NSFetchedResultsController(fetchRequest: fetchRequest,managedObjectContext: context,sectionNameKeyPath: nil,cacheName: nil)
    controller.delegate = self
    controller.performFetch(nil)

    return controller
}()

NSFetchResultController 委托方法

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    self.tableView.beginUpdates()
}


func controller(controller: NSFetchedResultsController,didChangeObject object: AnyObject,atIndexPath indexPath: NSIndexPath?,forChangeType type: NSFetchedResultsChangeType,
    newIndexPath: NSIndexPath?) {

    switch type {
    case .Insert:
        self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
    case .Update:
        self.tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
    case .Move:
        self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
        self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
    case .Delete:
        self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
    default:
        return
    }

}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    self.tableView.endUpdates()
}

TableView 委托方法

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 2
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return fetchedResultsController?.fetchedObjects?.count ?? 0
        }else {
            return newsroomFetchedResultsController?.fetchedObjects?.count ?? 0
        }


    }

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        if section == 1 {
            return (tableView.dequeueReusableCellWithIdentifier("section header") as? UITableViewCell)
        }

        return nil
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

            if let newItem = fetchedResultsController?.fetchedObjects?[indexPath.row] as? NewsItem  where indexPath.section == 0 {

                    if let cell = tableView.dequeueReusableCellWithIdentifier("main cell") as? NewMainTableViewCell where indexPath.row == 0{
                        cell.lblTitle.text = newItem.title
                        return cell

                    }
                    else if let cell = tableView.dequeueReusableCellWithIdentifier("new cell") as? NewTableViewCell{
                            cell.lblTitle.text = newItem.title
                            cell.backgroundColor = UIColor.blackColor()
                            cell.lblTitle.textColor = UIColor.whiteColor()
                            return cell
                    }


            }
            else if let newItem = newsroomFetchedResultsController?.fetchedObjects?[indexPath.row] as? NewsItem where indexPath.section == 1 {
                if let cell = tableView.dequeueReusableCellWithIdentifier("new cell") as? NewTableViewCell {
                    cell.lblTitle.text = newItem.title
                    cell.backgroundColor = UIColor.whiteColor()
                    cell.lblTitle.textColor = UIColor.blackColor()
                    return cell
                }
            }


        return UITableViewCell()
    }

    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if section == 1 {
            return 30
        }

        return 0
    }

    func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 0.001
    }

    func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return UIView(frame: CGRectZero)
    }

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if indexPath.section == 0 && indexPath.row == 0 {
            return UIScreen.mainScreen().bounds.width * 1.1
        }else {
            return 67
        }
    }

当我尝试运行它时出现此错误,并且 tableview 显示为空:

*2015-06-26 15:33:29.183 Kathimerini[5023:965439] *** 断言失败 -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44/UITableView.m:1623*

2015-06-26 15:33:29.183 Kathimerini[5023:965439] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (5) 必须等于更新前该节中包含的行数 (5),加上或减去数字从该部分插入或删除的行数(1 插入,0 删除)加上或减去移入或移出该部分的行数(0 移入,0 移出)。与 userInfo (null)

【问题讨论】:

    标签: ios swift core-data nsfetchedresultscontroller


    【解决方案1】:

    您的委托方法必须考虑到两个获取的结果控制器。在插入/删除等行的委托回调中,您应该首先检查

    if controller == self.fetchedResultsController {
       // modify section 1
    }
    else {
       // modify section 0
    }
    

    您可以通过首先设置获取结果控制器的委托来测试您的设置是否按预期工作。

    另外,请确保您了解索引路径的含义。主要 FRC 将报告例如要在索引路径(0,10) 处插入一个新项目,但您必须将其插入到(1,10) 处。 FRC 不知道您的部分,因为这是您的表视图的实现细节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多