UITableView 更新失败
Fail on UITableView update
需要你们的帮助!
我只对 iOS 9 上的错误感到生气。
正如您在下面看到的,它在 iOS 11
上进展顺利
一开始,我有 4 个状态为 "Nouveau" 的新单元格。
当我单击 "new" 单元格时,状态更改为 "En attente"(对于 "waiting")。
在 iOS9 上,直到最后一个单元格之前一切正常。当我点击最后一个 "new" 单元格时,它不会移动到 "waiting" 并且 "new" 部分仍然存在。在此之后,table 视图不再获得更新,当我切换到另一个 viewController 并返回包含 table 视图的视图时,它会恢复正常。
我正在使用 NSFetchedResultsController。数据很好,部分数量很好,按部分分类的元素数量很好,标题很好。
开头有 1 个标题为 "Nouveau" 的部分,有 4 个 objects
最后,1 个标题为 "En attente" 的部分和 4 个 objects
extension CRDashboardOrdersViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
print( self.fetchResult?.sections?.count ?? 0 )
return self.fetchResult?.sections?.count ?? 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print( self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0 )
return self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CRDashboardOrderTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CRDashboardOrderTableViewCell") as! CRDashboardOrderTableViewCell
let order: Order = self.fetchResult.object(at: indexPath) as! Order
cell.order = order
if let selectedIndexPath = self.selectedIndexPath, selectedIndexPath == indexPath {
self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
}
return cell
}
}
extension CRDashboardOrdersViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedIndexPath = indexPath
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print( self.fetchResult?.sections?.get(index: section)?.name ?? "???" )
return self.fetchResult?.sections?.get(index: section)?.name ?? "???"
}
}
extension CRDashboardOrdersViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
print(sectionIndex)
print(sectionInfo.indexTitle)
switch type {
case .insert:
self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
case .delete:
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
default:
break
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
self.tableView.reloadRows(at: [indexPath!], with: .fade)
if indexPath == self.selectedIndexPath {
self.selectedIndexPath = indexPath
}
break
case .insert:
self.tableView.insertRows(at: [newIndexPath!], with: .fade)
self.selectedIndexPath = nil
break
case .delete:
self.tableView.deleteRows(at: [indexPath!], with: .fade)
self.selectedIndexPath = nil
break
case .move:
self.tableView.moveRow(at: indexPath!, to: newIndexPath!)
if indexPath == self.selectedIndexPath {
self.selectedIndexPath = newIndexPath
}
break
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.endUpdates()
}
}
您的 cellForRow: 和 FetchedResults 委托有误。
当使用 FetchedResultsController 时,在 .update 上你不应该使用 reloadRows,这会导致问题,而你应该有一个像这样更新单元格模型的方法:
func updateCell(atPath indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? MyCell {
updateCell(withCell: cell, atIndexPath: indexPath)
}
}
func updateCell(withCell cell: MyCell, atIndexPath indexPath: IndexPath) {
if let MyModel = fetchedResultsController?.object(at: indexPath) {
cell.model = myModel
}
}
然后在您的委托 .update 中调用 updateCell(AtIndexPath) 来更新单元格 UI。
您还应该在 cellForRow 中使用此单元格配置方法
需要你们的帮助! 我只对 iOS 9 上的错误感到生气。 正如您在下面看到的,它在 iOS 11
上进展顺利一开始,我有 4 个状态为 "Nouveau" 的新单元格。 当我单击 "new" 单元格时,状态更改为 "En attente"(对于 "waiting")。
在 iOS9 上,直到最后一个单元格之前一切正常。当我点击最后一个 "new" 单元格时,它不会移动到 "waiting" 并且 "new" 部分仍然存在。在此之后,table 视图不再获得更新,当我切换到另一个 viewController 并返回包含 table 视图的视图时,它会恢复正常。
我正在使用 NSFetchedResultsController。数据很好,部分数量很好,按部分分类的元素数量很好,标题很好。
开头有 1 个标题为 "Nouveau" 的部分,有 4 个 objects 最后,1 个标题为 "En attente" 的部分和 4 个 objects
extension CRDashboardOrdersViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
print( self.fetchResult?.sections?.count ?? 0 )
return self.fetchResult?.sections?.count ?? 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print( self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0 )
return self.fetchResult?.sections?.get(index: section)?.numberOfObjects ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CRDashboardOrderTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CRDashboardOrderTableViewCell") as! CRDashboardOrderTableViewCell
let order: Order = self.fetchResult.object(at: indexPath) as! Order
cell.order = order
if let selectedIndexPath = self.selectedIndexPath, selectedIndexPath == indexPath {
self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
}
return cell
}
}
extension CRDashboardOrdersViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedIndexPath = indexPath
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print( self.fetchResult?.sections?.get(index: section)?.name ?? "???" )
return self.fetchResult?.sections?.get(index: section)?.name ?? "???"
}
}
extension CRDashboardOrdersViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
print(sectionIndex)
print(sectionInfo.indexTitle)
switch type {
case .insert:
self.tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
case .delete:
self.tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
default:
break
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
self.tableView.reloadRows(at: [indexPath!], with: .fade)
if indexPath == self.selectedIndexPath {
self.selectedIndexPath = indexPath
}
break
case .insert:
self.tableView.insertRows(at: [newIndexPath!], with: .fade)
self.selectedIndexPath = nil
break
case .delete:
self.tableView.deleteRows(at: [indexPath!], with: .fade)
self.selectedIndexPath = nil
break
case .move:
self.tableView.moveRow(at: indexPath!, to: newIndexPath!)
if indexPath == self.selectedIndexPath {
self.selectedIndexPath = newIndexPath
}
break
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.endUpdates()
}
}
您的 cellForRow: 和 FetchedResults 委托有误。
当使用 FetchedResultsController 时,在 .update 上你不应该使用 reloadRows,这会导致问题,而你应该有一个像这样更新单元格模型的方法:
func updateCell(atPath indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? MyCell {
updateCell(withCell: cell, atIndexPath: indexPath)
}
}
func updateCell(withCell cell: MyCell, atIndexPath indexPath: IndexPath) {
if let MyModel = fetchedResultsController?.object(at: indexPath) {
cell.model = myModel
}
}
然后在您的委托 .update 中调用 updateCell(AtIndexPath) 来更新单元格 UI。
您还应该在 cellForRow 中使用此单元格配置方法