当行数填满视图时,UITableView意外地通过beginUpdates()和CoreData与endUpdates() / performBatchUpdates() / NSFetchedResultsController反弹。
复制非常简单。
-从主从应用程序模板(带有CoreData)创建一个新项目。
-在情节提要中,删除“showDetail”设置。 (我们不需要详细视图)
-在MasterViewController中,将segue func prepare()替换为:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let event = fetchedResultsController.object(at: indexPath)
    let timestamp = event.timestamp
    event.timestamp = timestamp // The idea is to simply update the Event entity.
  }

启动应用程序(在iOS设备或模拟器中),并添加足够的行以填充视图(在iPhone SE中为11行)。
向下滚动视图,然后选择任何行。该视图将快速上下跳动。
那是一个错误,还是代码有问题?

最佳答案

好的,我可能已经找到了解决方案,请告诉我您的想法。
这个想法是在insert/delete/move中处理performBatchUpdates,然后将update保留在其中。
因此,我创建了以下枚举和属性:

enum FetchedResultsChange<Object> {
  case insert(IndexPath)
  case delete(IndexPath)
  case move(IndexPath, IndexPath, Object)
}
var fetchedResultsChanges: [FetchedResultsChange<Event>] = []

并且controllerWillChangeContent变为空:
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {}
didChange变为:
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch type {
    case .insert:
      self.fetchedResultsChanges.append(.insert(newIndexPath!))
    case .delete:
      self.fetchedResultsChanges.append(.delete(indexPath!))
    case .update:
      configureCell(tableView.cellForRow(at: indexPath!)!, withEvent: anObject as! Event) // So this stays untouched.
    case .move:
      self.fetchedResultsChanges.append(.move(indexPath!, newIndexPath!, anObject as! Event))
    }
  }
controllerDidChangeContent变为:
  func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    guard self.fetchedResultsChanges.count > 0 else { return }

    tableView.performBatchUpdates({
      repeat {
        let change = self.fetchedResultsChanges.removeFirst()
        switch change {
        case .insert(let newIndexPath):
          tableView.insertRows(at: [newIndexPath], with: .fade)
        case .delete(let indexPath):
          tableView.deleteRows(at: [indexPath], with: .fade)
        case .move(let indexPath, let newIndexPath, let event):
          configureCell(tableView.cellForRow(at: indexPath)!, withEvent: event)
          tableView.moveRow(at: indexPath, to: newIndexPath)
        }
      } while self.fetchedResultsChanges.count > 0
    }, completion: nil)
  }

所以你怎么看 ?

关于ios - 使用NSFetchedResultsController和CoreData,UITableView意外地与beginUpdates()/endUpdates()/performBatchUpdates()一起反弹,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50981504/

10-12 15:57