gpt4 book ai didi

ios - NSFetchedResultsController 不知道数据已被 NSBatchUpdateRequest 更改

转载 作者:行者123 更新时间:2023-11-28 23:22:32 25 4
gpt4 key购买 nike

长话短说

显然,当通过执行 NSBatchUpdateRequest 发生更改时,NSFetchedResultsController 不知道给定 NSManagedObjectContext 上的数据已更改。是否可以强制 NSFetchedResultsController 重新加载其数据,以便 NSFetchedResultsControllerDelegate 上的 controller(_:didChange:at:for:newIndexPath:) 被调用?

问题

我正在使用一个获取的结果 Controller 来了解基础数据的变化,这样我就可以在 TableView 发生变化时更新它。我正在采用 NSFetchedResultsControllerDelegate 协议(protocol)并实现 controller(_:didChange:at:for:newIndexPath:) 方法。一切似乎都正常,因为当我插入、删除或更新单个项目时调用了 did change 方法。

当我使用 NSBatchUpdateRequest 批量更新多个项目时会出现问题。当我这样做时,委托(delegate)方法 controller(_:didChange:at:for:newIndexPath:) 不会被调用(我在获取结果 Controller 使用的相同上下文中执行这些更新)。

代码

#1:获取结果 Controller 初始化:

func createFetchedResultsController() -> NSFetchedResultsController {
let fetchRequest: NSFetchRequest<EAlbum> = NSFetchRequest<EAlbum>(entityName: "EAlbum")
fetchRequest.predicate = NSCompoundPredicate(type: .and, subpredicates: createPredicates())
addSortDescriptors(on: fetchRequest)

let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: AppDelegate.myPersistentContainer.viewContext,
sectionNameKeyPath: nil,
cacheName: nil)

fetchedResultsController.delegate = self
return fetchedResultsController
}

#2:NSFetchedResultsControllerDelegate:

extension FeedTableViewController: NSFetchedResultsControllerDelegate {

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
didChange anObject: Any,
at indexPath: IndexPath?,
for type: NSFetchedResultsChangeType,
newIndexPath: IndexPath?) {
switch type {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
default:
// TODO
}
}

}

#3:我使用 NSBatchUpdateRequestAppDelegate.myPersistentContainer.viewContext 更新一堆项目的函数:

func markAllAsRead(using context: NSManagedObjectContext) -> Bool {
let request = NSBatchUpdateRequest(entityName: "EAlbum")
request.predicate = NSPredicate(format: "%K == YES", #keyPath(EAlbum.markUnread))
request.propertiesToUpdate = [#keyPath(EAlbum.markUnread): false]
request.resultType = .statusOnlyResultType

do {
let result = try context.execute(request) as? NSBatchUpdateResult
return result?.result as? Bool ?? false
} catch {
return false
}
}

#4:我只从 AppDelegate.myPersistentContainer.viewContext 更新一个项目的函数:

func updateUnreadFlag(albumId: String, markUnread: Bool, using context: NSManagedObjectContext) {
guard let album = try? EAlbum.findAlbum(matching: albumId, in: context) else { return }
album.markUnread = markUnread
do {
try context.save()
} catch {
// Handle error
}
}

#4 被调用时,委托(delegate) controller(_:didChange:at:for:newIndexPath:) 方法被调用。但是当执行 #3 时,委托(delegate)方法没有被调用。看起来 NSFetchedResultsController 并不知道给定的 NSManagedObjectContext 上的数据发生了变化,因为通过执行 NSBatchUpdateRequest 发生了这种变化。

我试过的解决方法

因为我的 fetched results controller 不知道数据被改变了,我想像这样手动重新加载它:

func reloadFetchedResultsController() {
fetchedResultsController = createFetchedResultsController()

do {
try fetchedResultsController.performFetch()
} catch {
// Handle error
}

tableView.reloadData()
}

所以每次执行#3 后,我都会调用reloadFetchedResultsController() 来重新加载获取的结果 Controller 和 TableView 。但出于某种原因,它似乎加载了旧数据,因为我的表格 View 没有任何变化。

问题

答:是否可以在执行批量更新时让抓取结果 Controller 知道数据已更改?

B: 是否可以强制我的 fetched results Controller 重新加载它的数据?因为,作为最后的手段,我可​​以在执行 #3 后强制重新加载我的获取结果 Controller ,最后强制更新 TableView ,因此它将使用新的批处理重新加载它的单元格-从获取的结果 Controller 更新数据。

最佳答案

来自documentation :

执行批量更新请求后,您必须将更改合并到上下文中。

尝试

func markAllAsRead(using context: NSManagedObjectContext) -> Bool {
let request = NSBatchUpdateRequest(entityName: "EAlbum")
request.predicate = NSPredicate(format: "%K == YES", #keyPath(EAlbum.markUnread))
request.propertiesToUpdate = [#keyPath(EAlbum.markUnread): false]
request.resultType = .updatedObjectIDsResultType

do {
let result = try context.execute(request) as? NSBatchUpdateResult
guard let objectIDArray = result?.result as? [NSManagedObjectID] else { return false }
let changes = [NSUpdatedObjectsKey : objectIDArray]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
return true
} catch {
return false
}
}

关于ios - NSFetchedResultsController 不知道数据已被 NSBatchUpdateRequest 更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59439779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com