【问题标题】:collectionView didSlectRow bugcollectionView didSlectRow 错误
【发布时间】:2019-10-12 13:24:22
【问题描述】:

您好,在我的项目的特定 viewController 上,我有一个带有自定义类单元格的 UICollectionView。但我有一个大问题:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("tapped on a cell")
    }

当点击一个单元格并立即释放(正常点击)它什么都不做,什么也不做。

如果我按住大约 1 秒而不松开手指,它会变成灰色,突出显示

如果我按住至少 3 秒松开手指 didSelectItemAt 会正确执行。 我试图在另一个项目上做同样的事情,这很好,但在这个 VC 上却没有,我真的没有发现问题。 VC Bugged 属于 Main.storyboard 中的 addTest 类

【问题讨论】:

  • 请不要链接到您的整个代码。相反,找出如何在一个最小的、完整的可验证示例中重现该问题。

标签: ios swift xcode debugging uicollectionview


【解决方案1】:

可能在集合视图下方有一个UIGesture 或其他可交互的东西。您应该在界面生成器禁用cancel touches in view的能力:

或在代码中:

myTapGestureRecognizer.cancelsTouchesInView = false

【讨论】:

  • 不客气。我无需查看您的项目就知道问题出在哪里,但@matt 是对的!您应该提供最小的完整可验证示例而不是整个项目。对于这种情况,一些关于当前视图控制器的层和类的代码的信息就足够了。
  • 非常有见地和聪明!但是,既然您已经如此出色地确定了问题的根源,我认为这不是正确的解决方案。我认为我们想要的是手势识别器上的委托,以防止仅在点击位于单元格中的情况下进行识别。
  • 谢谢,但我认为这对于还不太熟悉 iOS 的人来说已经足够了。我猜那是一个UITapGesture 仅用于keyboard dismissal。 (常见的初学者问题。)
【解决方案2】:

Mojtaba Hosseini 的洞察力非常聪明,但给出的答案可能并不完全正确。

原来主视图上有一个UITapGestureRecognizer;如果它在点击单元格之前识别,它会阻止单元格选择。但是,如果您只是在该手势识别器上将cancelsTouchesInView 设置为false,那么它们 会起作用,这似乎不太可能是我们想要的。我们当然想要单元格点击而不是点击手势识别器点击。

因此,正确的解决方案是给点击手势识别器一个委托并实现gestureRecognizerShouldBegin。在这里,我们查看水龙头的位置。如果它在一个单元格的范围内,我们返回false;否则我们返回true。因此,我们在单元格点击和手势识别器点击之间进行调解。

这是一个可能的实现,以高度简化的形式演示:

extension UIView {
    func isDescendant(of whattype:UIView.Type) -> Bool {
        var sup : UIView? = self.superview
        while sup != nil {
            if (whattype == type(of:sup!)) {
                return true
            }
            sup = sup!.superview
        }
        return false
    }
}

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        let t = UITapGestureRecognizer(target: self, action: #selector(tap))
        self.view.addGestureRecognizer(t)
        t.delegate = self
    }

    @objc func tap(_:UIGestureRecognizer) {
        print("tap")
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("select")
    }

    func gestureRecognizerShouldBegin(_ gr: UIGestureRecognizer) -> Bool {
        if let v = gr.view {
            let loc = gr.location(in: v)
            if let v2 = v.hitTest(loc, with: nil) {
                return !v2.isDescendant(of: UICollectionViewCell.self)
            }
        }
        return true
    }
}

如您所见,我们查看点击是否在集合视图单元格内;如果是,我们的手势识别器将无法识别,并且选择立即成功。

【讨论】:

  • 是的,马特它更可靠但是因为我猜Gesture 可能只处理键盘关闭,也许这不是必需的,它的方式更复杂。
猜你喜欢
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
相关资源
最近更新 更多