两个 NSFetchResultControllers ,一个 TableViewController

Posted

技术标签:

【中文标题】两个 NSFetchResultControllers ,一个 TableViewController【英文标题】:Two NSFetchResultControllers , One 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)

【问题讨论】:

【参考方案1】:

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

if controller == self.fetchedResultsController 
   // modify section 1

else 
   // modify section 0

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

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

【讨论】:

以上是关于两个 NSFetchResultControllers ,一个 TableViewController的主要内容,如果未能解决你的问题,请参考以下文章

写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果两个整数由键盘输入。

怎么查两个地方的距离?

Markdown怎么输入两个$?

右边按键上RF两个按键是控制啥的?

Xcode:如何为指向两个不同团队帐户(企业和公司)的两个不同目标选择两个不同的应用程序组

两个行列式怎么相加?