防止多个pannable表视图单元被淘汰

时间:2016-12-12 03:30:31

标签: swift uitableview uipangesturerecognizer

使用UIPanGestureRecognizer我的细胞可以平移。我的问题是,我只希望一次淘汰一个单元格。为此,我添加了一些尝试:

选项1,为每个单元格使用Bool属性:

class PannableCell: UITableViewCell {

    weak var controller: TableViewController? 

    var isPanning = false

    let panGesture = UIPanGestureRecognizer()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        panGesture.addTarget(self, action: #selector(handlePan))

        contentView.addGestureRecognizer(panGesture)
    }

    func handlePan(recognizer: UIPanGestureRecognizer) {
        guard let cells = controller?.tableView.visibleCells.filter({ $0 != self }) else { return }
        guard !cells.contains(where: { ($0 as? PannableCell)?.isPanning ?? false }) else { return }

        if recognizer.state == .began { isPanning = true }

        if recognizer.state == .changing { } //moving cell

        if recognizer.state == .ended {
            UIView.animate(withDuration: 0.5, animations: { }) {
                 if $0 { self.isPanning = false } 
            }
        }
    }
}

使用此代码,一次只能平移一个单元格。不幸的是,有些情况(约5-10%)可以淘汰多个细胞。我怀疑它与被淘汰或敲击时重复使用的细胞有关。

我知道我应该让视图控制器处理MVC模型中所述的控件。我不确定它是否能解决之前提到的问题。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

你可以这样做:

if recognizer.state == .began { self.isPanning = true }

我想在你设置isPanning = true之前,识别器可以触发对你的句柄方法的另一个调用,这个调用也将通过,并且最终都将结束:

if recognizer.state == .began { isPanning = true }

我不知道这是什么语言,但你必须使用一些锁来在handle方法的开头和检查状态后阻塞线程。开始你可以释放锁,因此在方法的乞讨条件下将看到已经有一个isPanning = true的单元格。你也可以使把手线程安全!

好的,我读了一些关于它的内容,显然在swift中没有良好的同步,但是有足够好的文档。检查了这一个:

https://developer.apple.com/reference/uikit/uigesturerecognizerdelegate

在您的情况下,您必须添加一个委托并实施:

optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool

试试这样:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    panGesture.delegate = self 

    panGesture.addTarget(self, action: #selector(handlePan))

    contentView.addGestureRecognizer(panGesture)
}

func gestureRecognizer(UIGestureRecognizer, shouldRequireFailureOf:UIGestureRecognizer) -> Bool {
    if (gestureRecognizer == panGesture && (otherGestureRecognizer.view.isDescendantOfView(gestureRecognizer.view)) {
        return true
        } else {
        return false
    }
}