ios - NSFetchedResultsController 添加新记录时如何防止 UITableView 向上滚动?

标签 ios swift uitableview nsfetchedresultscontroller

一旦我向 CoreData 添加新评论,我的 UITableView 就会向上滚动。 NSFetchedResultsController 知道它,将此评论放在表的底部,并将表滚动到顶部。正常吗?

我的例子:

就在我添加评论之前:

enter image description here

就在我添加评论之后(不是预期的行为):

enter image description here

应该是这样的(我手动手动刷过之后):

enter image description here

这可能与以下情​​况有关:

  1. 这是我的 NSFetchedResultsController 的排序描述符:

    NSSortDescriptor(key: "createdAt", ascending: false) //from the latest to the oldest
    
  2. 但我需要显示我对反向索引路径的评论(最新的在最底部)。换句话说,当我需要使用 indexPath 时,我会在任何地方使用:

    private func reversedIndexPathForIndexPath(indexPath: NSIndexPath) -> NSIndexPath {
        return NSIndexPath(forRow: fetchedResultsController.fetchedObjects!.count - indexPath.row - 1, inSection: 0)
    }
    

NSFetchedResultsControllerDelegate:

//MARK: - NSFetchedResultsControllerDelegate

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    self.tableView.beginUpdates()
}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    switch type {
    case .Insert:
        if let newIndexPath = newIndexPath {
            tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
        }
    case .Delete:
        if let indexPath = indexPath {
            tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
        }
    case .Update:
        if let indexPath = indexPath {
            tableView.reloadRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
        }
    case .Move:
        if let indexPath = indexPath, let newIndexPath = newIndexPath {
            tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
            tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
        }
    }
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}

它与我的问题有关吗?

最佳答案

编辑后的答案:

我能够通过以下步骤重现此故障:

  1. UITableView,其 rowHeight 设置为 UITableViewAutomaticDimension 和非零 estimatedRowHeight
  2. 表格滚动到最底部,最后一个单元格在底部边缘完全可见。
  3. 将新单元格插入最后一个单元格下方会导致单元格的视觉偏移向下几个点(在我的设置中,它从 5 到 40 不等)。

此行为的来源需要进一步调查。

目前唯一的解决方案是不使用 UITableViewAutomaticDimension 并从 tableView:heightForRowAtIndexPath: 返回行高。

顺便说一句,倒排索引路径的实现有一个重大缺陷。当 FRC 调用它的委托(delegate)方法 controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: 时,所有删除索引路径都属于更改前数据集,所有插入索引路径都属于更改后数据集。当你在 controllerWillChangeContent:controllerDidChangeContent: 之间时,fetchedResultsController.fetchedObjects 将包含更改后的数据集,我想(需要不过检查过)。

关于ios - NSFetchedResultsController 添加新记录时如何防止 UITableView 向上滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33012157/

相关文章:

javascript - parse.com 云代码防止重复错误

ios - 如何修复窗口上的库菜单(用于 Storyboard )(Xcode 10)

ios - 如何在iPhone 4.0中配置注销

swift - 怎么去掉 map 上的绘制路线

ios - SceneKit:将创作软件中的 3D 角色导入场景?

ios - View Controller 关闭并重新出现以前的 View Controller

swift - 更改 UINavigationBar 的分隔符颜色

iphone - 文字转语音:阅读列表并在标题之间播放音频文件

ios - 如何在自定义 UITableViewCell 中创建 UIImageVIew? ( swift )

ios - cellForRowAtIndexPath 的替代方案