ios - NSFetchedResultsController 没有正确更新 tableView
问题描述
我在 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
}()
这就是我创建和添加新消息的方式
func createNewTextMessage(recipientId: String, content: String) {
...
guard let id = Int32(recipientId) else { return }
guard let chat = fetchSingleChat(recipientId: id) else { return }
let context = persistentContainer.viewContext
let message = Message(context: context)
let date = Date()
message.chatId = chat.id
message.createdAt = date
message.isRead = false
message.senderId = Int32(currentUserId)
message.senderName = currentUserName
message.senderPhoneNumber = currentUserPhoneNumber
message.status = MessageStatus.unsent.rawValue
message.type = MessageType.text.rawValue
message.owner = MessageOwnerType.mine.rawValue
message.content = content
message.recipientId = chat.recipientId
message.recipientName = chat.title
message.messageId = "\(currentUserToken)_\(date.millisecondsSince1970)"
// here's where i'm setting some relationship (chat to message: 1-to-many)
message.chat = chat
chat.lastMessage = message
message.chat?.lastMessage = message
do {
try context.save()
} catch let err {
print("failed to save private chat:", err)
}
}
聊天 ManagedObject 有一个 lastMessage 属性,它是消息类型(也是一个托管对象),我将新创建的消息设置为聊天的最后一条消息。问题可能来自那里。这里也是委托代码:
// 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()
}
解决方案
请注意,您对移动行 (.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)
}
推荐阅读
- css - 使用css网格在移动视图中拉伸的图像
- javascript - express 中路由控制器模型的问题
- c# - 使用 WHERE NOT EXISTS (SELECT TOP 1 (id) FROM table WHERE aaa LIKE @aaa AND 不会返回没有 AND 的结果
- ios - 通过 UIStoryBoardSegue 发送位置名称变量未显示
- laravel - Laravel @include 带有来自函数的变量的视图
- express - Node Express JEST Supertest PUT 和 DELETE 端点返回 405“方法不允许”
- java - Postgresql 从具有引用的其他表中加载所有值
- python - 从日期时间列中提取月份日期以使用 Seaborn 绘制季节性折线图
- mysql - 在mysql中将数字按45分组
- python - 为什么当我在 python 中按下按钮“运行”时它没有给出任何输出?