将NSFetchedResultsController与UITableView同步

时间:2016-08-19 04:48:11

标签: ios swift uitableview core-data

在我的聊天应用中," lastMessage"是朋友和消息实体之间的关系。每个Friend实体都有一组消息,只有一个lastMessage。因此,如果我向账单发送消息,请注明" lastMessage"将更新为更新的时间戳。也就是说,fetchedResultsController的获取对象包含每个朋友的lastMessage.timestamp的数组。我遇到的问题是UITableView。如果我在chatController中向朋友发送消息,然后按下" messageTable.reloadData"在我发信息的朋友DidChangeContent内部,他的lastMessage被更新为最新的时间戳,并被排序为fetchedResultsController中的第一个条目,将他移动到tableview的第一个位置。但是,由于我希望通过在didChangeObject中使用self.messagesTable.reloadRowsAtIndexPaths([indexPath!],withRowAnimation:UITableViewRowAnimation.None)来添加动画,所以没有任何内容正在正确地重新加载。我尝试将它插入.Insert,.Update和.Move一次。我非常擅长将NSFetchedResultsController同步到tableView。因此,我不确定如何通过NSFetchedResultsController正常实现重新加载表。

 @IBOutlet weak var messagesTable: UITableView!

lazy var fetchedResultsController: NSFetchedResultsController = {
    let fetchRequest = NSFetchRequest(entityName: "Friend")
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "lastMessage.timestamp", ascending: false)]
    let predicate = NSPredicate(format: "lastMessage.timestamp != nil")
    fetchRequest.predicate = predicate
    let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    frc.delegate = self
    return frc

}()



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

    if type == .Insert {

        self.messagesTable.reloadRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])
        self.messagesTable.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])


    }

    if type == .Update{
        // self.collectionView?.cha([newIndexPath!])
        print("h")
        self.messagesTable.reloadRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])
        self.messagesTable.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])


    }

    if type == .Move{
        // self.collectionView?.cha([newIndexPath!])
        print("h")
        self.messagesTable.reloadRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])
        self.messagesTable.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.None)//reloadItemsAtIndexPaths([indexPath!])


    }

}


func controllerDidChangeContent(controller: NSFetchedResultsController) {

    self.messagesTable.beginUpdates()


    }

1 个答案:

答案 0 :(得分:1)

使用reloadRowsAtIndexPathsinsertRowsAtIndexPaths方法代替deleteRowsAtIndexPaths。另外,在beginUpdates方法中使用controllerWillChangeContent,在endUpdates中使用controllerDidChangeContent。例如:

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

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
    switch type {
        case .Insert:
            self.messagesTable.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        case .Delete:
            self.messagesTable.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
        default:
            return
    }
}

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

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

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