背景:在tableView中,每个单元格都包含一个显示为图像的按钮。我想要显示的效果是,当我点击图像(实际上是按钮)时,按钮的图像会变为另一个图像。
错误:假设有很多数据(超过一页),如果我点击一个单元格的按钮,按钮的图像会改变,但副作用是整个表格查看首先向上滚动一点(如弹跳效果),然后向下滚动到前一个位置
我做了什么:
inboxListTableView.estimatedRowHeight = 60
inboxListTableView.rowHeight = UITableViewAutomaticDimension
当我点击按钮时(true和false表示不同的图像和tableView(cellForRowAtIndex :)方法中的定义):
let cell = sender.superview?.superview as InboxListCellTableViewCell
if let indexPath = inboxListTableView.indexPathForCell(cell) {
let actionToUpdate = actions[indexPath.row]
actionToUpdate.imageButton = !actionToUpdate.imageButton.boolValue
var e: NSError?
if !MOContext.save(&e) {
println(e?.description)
}
}
然后在获取结果控制器委托方法中:
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()
}
我认为这个bug可能由两个方面引起:CoreData和Self sizing cell(动态单元格高度)。因为当我使用数组来保存动作([Action])而不是CoreData时,我没有遇到错误。但是,当我对此代码发表评论inboxListTableView.rowHeight = UITableViewAutomaticDimension
时,它没有反弹/向上滚动"但是牢房的高度是固定的。
有什么想法吗?什么都可以帮忙!谢谢:))
答案 0 :(得分:1)
我遇到了完全相同的问题:使用动态细胞高度时会有一点反弹。我的情况不同,我没有使用NSFetchedResultsController,我也改变了单元格的高度(展开和折叠它们)。
经过大量的实验,我找到了一个简单的解决方案。只需在reloadRowsAtIndexPaths之后调用scrollToRowAtIndexPath。它对我有用。
tableView.reloadRows(at: [indexPath], with: .none)
tableView.scrollToRow(at: indexPath, at: .none, animated: true)
当我展开和折叠单元格时,我调用此代码。 我希望你能在项目中使用它。
答案 1 :(得分:0)
我认为问题的实用解决方案是不使用NSFetchedResultsControllerDelegate
方法进行此特定更新。
您可以直接在按钮处理程序中更改按钮的图像。您必须在获取结果控制器委托的.Update
情况下检查此情况,并确保不调用reloadRowsAtIndexPaths
方法。
现在您正在避免自动UI更新机制,并且不应该发生此问题。
顺便说一句,依靠表视图单元的视图层次结构访问索引路径(superview.superview...
)是非常糟糕的做法。几年前,Apple改变了细胞的工作方式,依赖类似范例的代码也破裂了。与集合视图单元格相同。
相反,做这样的事情:
func buttonHandler(sender: UIButton) {
let point = sender.convertPoint(CGPointZero, toView:self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(point)
}