如果在滑动过程中快速点击,则不会调用UITableView tableView(_:didEndEditingRowAt :)

时间:2017-05-23 03:16:10

标签: ios iphone swift uitableview

我有一个UITableVieweditAction可通过向左滑动访问。

似乎有一个内置的UITableView功能,如果您滑动单元格以显示编辑操作,然后点击tableView中的任意位置,操作将自动滑动关闭,{{1}调用}来通知代理编辑结束。

然而,我看到的问题是,有时候,如果你向左滑动然后在滑动后很快(当只有一小部分编辑动作可见且动画正在进行时),你可以点击任何地方否则屏幕上的编辑操作已关闭但didEndEditingRowAt未被调用!

因此,使用以下代码,我们最终将tableView置于编辑模式,但没有打开视图,最后一行打印为didEndEditingRowAt,确认从未调用过Will Edit

didEndEditingRowAt

现在,这种情况有时只会发生,并且有点难以确定正确的时机,但它绝对可以重现。

以下是整个演示的链接:https://github.com/gregkerzhner/SwipeBugDemo

我在这里做错了什么?在我的真实项目中,我的代码会淡化其他单元格以关注当前正在编辑的单元格,并且最终处于其他单元格褪色的错误状态,但是聚焦单元格没有打开任何编辑操作。 / p>

4 个答案:

答案 0 :(得分:2)

这绝对是UITableView中的一个错误,它保留在"编辑"即使刷卡反弹(例如,如果你只是稍微滑动一下)也说明了状态。

好消息是,您可以使用一些UITableViewCell方法来查找解决方法。 UITableViewCell具有相应的方法,用于通知与操作相关的状态更改:

func willTransition(to state: UITableViewCellStateMask)
func didTransition(to state: UITableViewCellStateMask)
func setEditing(_ editing: Bool, animated: Bool)
var showingDeleteConfirmation: Bool { get }

转换(和动画)开始和结束时调用转换方法。当您滑动时,系统会调用willTransitiondidTransition(状态为.showingDeleteConfirmationMask),showingDeleteConfirmation将为truesetEditing也会调用true

虽然这仍然是错误的(除非您实际公布按钮,否则单元格不能成功编辑),didTransition是一个回调,您可以在其中检查动作视图是否确实可见。我不认为有任何可靠的方法可以做到这一点,但也许只是检查单元格contentView占用大部分边界就足够了。

答案 1 :(得分:2)

所以最后,工作解决方案最终与@ncke和@hybridcattt建议的有点不同。

@ ncke解决方案的问题在于,在此滑动/点按互动期间未调用func scrollViewDidEndDecelerating(_ scrollView: UIScrollView),因此永远不会调用变通方法。

@ hybridcattt解决方案的问题是那些UITableViewCell回调过早被调用,所以如果你进行快速轻击操作,UITableViewCellDeleteConfirmationView仍然是单元格子视图的一部分那些回调被调用。

最好的方法似乎是覆盖willRemoveSubview(_ subview: UIView)的{​​{1}}功能。每次UITableViewCell被删除时,无论是在正常滑动关闭期间,还是在这种快速滑动快速点击方案中,都会可靠地调用此方法。

UITableViewCellDeleteConfirmationView

正如@hybridcattt和@ncke建议的那样,在您的控制器中,您可以挂钩此代理并将缺少的事件发送到 protocol BugFixDelegate { func editingEnded(cell: UITableViewCell) } class CustomCell: UITableViewCell { weak var bugFixDelegate: BugFixDelegate? override func willRemoveSubview(_ subview: UIView) { guard String(describing: type(of: subview)) == "UITableViewCellDeleteConfirmationView" else {return } endEditing(true) bugFixDelegate.editingEnded(cell: self) } } UITableView

UITableViewDelegate

答案 2 :(得分:1)

我并不是说这是有史以来最好的事情,但如果你想要一个解决方法,这可能是一个开始:

extension UITableView {

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        for cell in self.visibleCells {
            if cell.isEditing && (cell.subviews.count < 3 || cell.subviews[2].frame.origin.x < 30.0) {

                print("\(cell) is no longer editing")
                cell.endEditing(true)
                if let indexPath = self.indexPath(for: cell) {
                    self.delegate?.tableView?(self, didEndEditingRowAt: indexPath)
                }
            }
        }
    }

}

这个想法是UITableView是UIScrollView的子类。虽然前者的代表方法似乎已被打破,但后者仍在被召唤。一些实验产生了这个测试。

只是一个想法:)您可能更喜欢继承UITableView而不是扩展,以本地化黑客。

答案 3 :(得分:0)

这是我的解决方案。享受。

func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
    if #available(iOS 10.0, *) {
    return .none;
    } else {
        return .delete;
    }
}