Ios NSFetchedResultsController未正确更新tableView
我在viewDidLoad中获取一些项(NSManagedObject),并使用NSFetchedResultsController委托更新swift ios中的tableView单元格(来自Apple文档的用于插入、删除等的委托),问题是,当我向相同ManagedObject类型的核心数据添加项时,我希望该表使用新项更新,但是,最后一项将从tableview中删除,而新项不会添加。我只在再次加载屏幕时看到新项目。。。有什么不对劲吗? 这是我的fetchedResultsController:Ios NSFetchedResultsController未正确更新tableView,ios,swift,uitableview,core-data,Ios,Swift,Uitableview,Core Data,我在viewDidLoad中获取一些项(NSManagedObject),并使用NSFetchedResultsController委托更新swift ios中的tableView单元格(来自Apple文档的用于插入、删除等的委托),问题是,当我向相同ManagedObject类型的核心数据添加项时,我希望该表使用新项更新,但是,最后一项将从tableview中删除,而新项不会添加。我只在再次加载屏幕时看到新项目。。。有什么不对劲吗? 这是我的fetchedResultsController:
lazy var fetchedResultsController: NSFetchedResultsController<Message> = {
let context = CoreDataManager.shared.persistentContainer.viewContext
let request: NSFetchRequest<Message> = Message.fetchRequest()
request.sortDescriptors = [
NSSortDescriptor(key: "createdAt", ascending: true)
]
request.fetchLimit = 40
let frc = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
// fetch only messages with that recipient id of the chat.
let recipientId = "\(chat!.recipientId)"
request.predicate = NSPredicate(format: "recipientId == %@", recipientId)
return frc
}()
聊天管理对象有一个属性lastMessage,它是Message类型(也是一个托管对象),我将新创建的消息设置为聊天的最后一条消息。问题可能就在那里。
下面是代理代码:
// MARK: - NSFetchedResultsController Delegates
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
switch type {
case .insert:
tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
case .delete:
tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
case .move:
break
case .update:
break
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .right)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .fade)
case .update:
tableView.reloadRows(at: [indexPath!], with: .fade)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
//标记:-NSFetchedResultsController委托
func controllerWillChangeContent(\ucontroller:NSFetchedResultsController){
tableView.beginUpdate()
}
func控制器(控制器:NSFetchedResultsController,didChange sectionInfo:NSFetchedResultsSectionInfo,atSectionIndex sectionIndex:Int,类型:NSFetchedResultsChangeType){
开关类型{
案例.插入:
tableView.insertSections(IndexSet(整数:sectionIndex),带:.fade)
案例.删除:
tableView.deleteSections(IndexSet(整数:sectionIndex),带:.fade)
案件.动议:
打破
案例。更新:
打破
}
}
func控制器(controller:NSFetchedResultsController,didChange anObject:Any,在indexPath:indexPath?处,对于类型:NSFetchedResultsChangeType,newIndexPath:indexPath?){
开关类型{
案例.插入:
tableView.insertRows(位于:[newIndexPath!],带:。右侧)
案例.删除:
tableView.deleteRows(位于:[indexPath!],带:.fade)
案例。更新:
tableView.reloadRows(位于:[indexPath!],带:.fade)
案件.动议:
tableView.moveRow(at:indexPath!,to:newIndexPath!)
}
}
func controllerDidChangeContent(\控制器:NSFetchedResultsController){
tableView.endUpdates()
}
请注意,您对移动行(.move)的处理只移动一行,您应该实现它以移动多行。不确定这是否解决了问题,这取决于数据的排序方式
下面是我如何实现我的.move
case .move:
if let indexPath = indexPath {
tableView.removeRows(at: IndexSet(integer: indexPath.item), withAnimation: .effectFade)
}
if let newIndexPath = newIndexPath {
tableView.insertRows(at: IndexSet.init(integer: newIndexPath.item), withAnimation: .effectFade)
}
... 我正在使用NSFetchedResultsController委托。你在哪里设置代理?代理在viewDidLoad中设置,我也在那里进行抓取。也许你也应该向我们显示代理代码。我已经添加了代理代码。我的排序是基于日期的。此外,排序是否会触发移动?因为我只是像我说的那样插入新项目,我不确定它是否解决了您的问题,也许您可以尝试一下,但它仍然是一个改进,因为它处理多行就像您的其他开关情况一样。如果没有帮助,我会删除这个答案。
case .move:
if let indexPath = indexPath {
tableView.removeRows(at: IndexSet(integer: indexPath.item), withAnimation: .effectFade)
}
if let newIndexPath = newIndexPath {
tableView.insertRows(at: IndexSet.init(integer: newIndexPath.item), withAnimation: .effectFade)
}