Ios 调用reloadRowsAtIndexPaths方法时导致反弹效果的动态单元格高度

Ios 调用reloadRowsAtIndexPaths方法时导致反弹效果的动态单元格高度,ios,uitableview,core-data,Ios,Uitableview,Core Data,背景:在表格视图中,每个单元格都包含一个按钮,显示为图像。我想显示的效果是,当我单击图像(实际上是按钮)时,按钮的图像会变为另一个。 Bug:假设有很多数据(在一个页面上),如果我单击一个单元格的按钮,按钮的图像将发生变化,但会产生一个副作用,即整个tableView将首先向上滚动一点(像反弹效果),然后向下滚动到前一个位置。 我所做的: 在ViewDidLoad方法中:inboxListTableView.EstimateDrowEight=60 inboxListTableView.rowH

背景:在表格视图中,每个单元格都包含一个按钮,显示为图像。我想显示的效果是,当我单击图像(实际上是按钮)时,按钮的图像会变为另一个。
Bug:假设有很多数据(在一个页面上),如果我单击一个单元格的按钮,按钮的图像将发生变化,但会产生一个副作用,即整个tableView将首先向上滚动一点(像反弹效果),然后向下滚动到前一个位置。
我所做的

  • 在ViewDidLoad方法中:
    inboxListTableView.EstimateDrowEight=60
    inboxListTableView.rowHeight=UITableViewAutomaticDimension
  • 当我单击按钮时(true和false表示tableView(CellForRowatinex:)方法中的不同图像和定义):

  • 然后在获取结果控制器委托方法中:

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        inboxListTableView.beginUpdates()
    }
    
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath!) {
        switch type {
        case .Insert:
            inboxListTableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        case .Delete:
            inboxListTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        case .Update:
            inboxListTableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
        default:
            inboxListTableView.reloadData()
        }
        actions = controller.fetchedObjects as [Action]
    }
    
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        inboxListTableView.endUpdates()
    }
    
  • 我认为该缺陷可能由两个方面引起:CoreData和自调整单元格大小(动态单元格高度)。因为当我使用数组来保存操作([Action])而不是CoreData时,我没有遇到错误。但是,当我对这段代码进行注释时,它不是“反弹/向上滚动”,而是单元格的高度是固定的。


    有什么想法吗?任何事都能帮上忙!谢谢:)

    我认为解决您问题的实用方法是简单地而不是
    使用
    NSFetchedResultsControllerDelegate
    方法进行此特定更新

    您可以直接在按钮处理程序中更改按钮的图像。您必须在fetched results controller委托的
    .Update
    案例中检查这种情况,并确保不调用
    重新加载rowsatindexpaths
    方法

    现在,您正在避免使用自动UI更新机制,因此不应出现此问题

    顺便说一句,依赖表视图单元格的视图层次结构来访问索引路径(
    superview.superview…
    )是非常糟糕的做法。几年前,苹果改变了细胞的工作方式,并打破了依赖于类似范例的代码。集合视图单元格也是如此

    相反,可以这样做:

    func buttonHandler(sender: UIButton) {
        let point = sender.convertPoint(CGPointZero, toView:self.tableView)
        let indexPath = self.tableView.indexPathForRowAtPoint(point)
    }
    

    我有完全相同的问题:使用动态单元格高度时有一点反弹。我的例子的不同之处在于,我没有使用NSFetchedResultsController,而且我还更改了单元格的高度(展开和折叠)

    经过大量的实验,我找到了一个简单的解决办法。只需在重新加载rowsatindexpaths后调用ScrollToRowatineXpath。这对我有用

    tableView.reloadRows(at: [indexPath], with: .none)
    tableView.scrollToRow(at: indexPath, at: .none, animated: true)
    
    我在展开和折叠单元格时调用此代码。
    我希望您可以在项目中使用此功能。

    我注意到您有行动画
    。无。为什么?@Mundi起初我把它设置为“.Fade”,但仍然有这个问题,所以我把它改为“.None”,我认为它可能会起作用。这与你的更新逻辑有关。您正在更改托管对象的布尔属性。基于此,您正在显示imageA或imageB。也许您应该在问题中添加
    CellForRowatineXpath
    的实现。现在,我可以在单击按钮时更改按钮的图像,并在CellForRowatineXmethod中配置单元格的内容。问题是一切都是正确的,但tableview会反弹一点:(不过还是要谢谢你!@MundiThank你提供了获取tableView的方法!!但遗憾的是,删除“reloadRowsAtIndexPaths”方法的方式可能不起作用。我根据你的建议从两个方面修改了代码:1我删除了“.Update”开关盒。2在buttonAction方法中,我使用
    sender.setImage(UIImage)更改了发件人(UIButton)的图像(名称:imageName),forState:.Normal)
    。现在,在运行时,相应按钮的图像可以成功更改,但tableView仍会像以前一样向上滚动。谢谢!此外,当我使用假数据(将tableView数据源存储在数组中)时,不会显示这种反弹效果,当时我使用了
    reloadRowsAtIndexPaths
    方法。非常感谢!!@MundiSimple和伟大的解决方案
    tableView.reloadRows(at: [indexPath], with: .none)
    tableView.scrollToRow(at: indexPath, at: .none, animated: true)