[英]NSFetchedResultsController not inserting objects into UITableView correctly
[英]Inserting/Deleting into UITableView with NSFetchedResultsController
我对 Swift 开发相对较新,并且在使用 NSFetchedResultsController 时,我正在努力用新实体 (CoreData) 更新 UITableView。
我在互联网上搜索并遵循了各种教程,但是尽管遵循了它们,但当我将其转换为我的情况时,出现了一些问题,经过数小时的摸索,我似乎看不出有什么问题。
我希望将数据存储在 tableView 中,允许向左滑动以删除,并有一个用于为表创建新数据的表单。 我有插入工作,但没有删除,现在有删除工作,但没有插入。
我有上下文变量并像这样收集我的数据:
func loadData() {
let request = MyData.fetchRequest() as NSFetchRequest<MyData>
let sort = NSSortDescriptor(key: #keyPath(MyData.name), ascending: true)
request.sortDescriptors = [sort]
do {
myResults = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: #keyPath(MyData.name), cacheName: nil)
try myResults.performFetch()
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
myTableView.reloadData()
}
我正在尝试添加数据(当用户点击按钮时),如下所示:
let newData = MyData(entity: MyData.entity(), insertInto: context)
newData.name = newName
newData.colour = Int16(newDataPicker.selectedRow(inComponent: 0))
newData.dataID = dataID
appDelegate.saveContext()
loadData()
这没有问题,但是每次我尝试删除时,我都会因为 model 数据和 TableView 不同步而崩溃。 经过大量研究,我实现了 NSFetchedResultsControllerDelegate,如下所示:
extension ViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.myTableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .delete:
self.myTableView.deleteRows(at: [indexPath! as IndexPath], with: .fade)
// case .insert:
// self.myTableView.insertRows(at: [newIndexPath! as IndexPath], with: .fade)
default:
break
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.myTableView.endUpdates()
}
}
现在可以让我精美地删除。 不幸的是,我现在无法添加,因为这会使我的应用程序因Invalid update
错误而崩溃。
我已经尝试使用 NSFetchedResultsControllerDelegate 来处理插入,使用context.insert()
但这也会导致崩溃。
请有人能告诉我我犯了什么愚蠢的错误吗? 非常感谢!
您正在执行太多不必要的步骤,这会混淆NSFetchedResultsController
的功能。
删除和插入记录后,controller 在保存上下文后立即自动更新 UI
首先,按照 CoreData 模板中的建议创建一个NSFetchedResultsController
实例作为惰性实例化属性并设置委托。
lazy var fetchedResultsController: NSFetchedResultsController<MyData> = {
let request = MyData.fetchRequest() as NSFetchRequest<MyData>
let sort = NSSortDescriptor(key: #keyPath(MyData.name), ascending: true)
request.sortDescriptors = [sort]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: #keyPath(MyData.name), cacheName: nil)
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch {
print(error)
}
return aFetchedResultsController
}()
将loadData
替换为
func loadData()
{
do {
try fetchedResultsController.performFetch()
tableView.reloadData()
} catch {
print(error)
}
}
并在didChange
方法中实现所有类型
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: .fade)
case .delete: tableView.deleteRows(at: [indexPath!], with: .fade)
case .update: tableView.reloadRows(at: [indexPath!], with: .automatic)
case .move: tableView.moveRow(at: indexPath!, to: newIndexPath!)
@unknown default:
fatalError("New case in controller:didChange:at:for:")
}
}
如果 controller 也应该管理部分实施
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
switch type {
case .insert: tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic)
case .delete: tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
default: return
}
}
现在在上下文中插入一条记录或从上下文中删除一条记录。 然后保存上下文——没有别的——获取结果 controller 执行 rest。 不要调用loadData
也不要额外重新加载表视图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.