UICollectionView 的 didSelectItemAt 方法没有被调用

15

我感到困惑,因为这只是一件简单的事情,但它不起作用。

在写问题之前,这是我的检查清单:

  1. 已注册UICollectionViewDelegate

  2. "Debug View Hierarchy"中,UICollectionView上面没有其他视图

  3. UICollectionView和UICollectionViewCell的isUserInteractionEnabled属性均为true

  4. UICollectionView的isAllowsSelection属性为true

还有什么其他需要我检查的吗?

=====

class MyView: NibDesignable { // It's UIView with NibDesignableProtocol (https://github.com/mbogh/NibDesignable)
    @IBOutlet weak var collectionView: UICollectionView!

    override init(frame: CGRect) {
        super.init(frame: frame)

        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.setup()
    }

    private func setup() {
        print("test - It's called.")

        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.isUserInteractionEnabled = true
        self.collectionView.isAllowsSelection = true
    }
}

extension MyView: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath {
        print("test - It's not called")
    }
}
我只复制了与问题相关的部分,因为所有代码太长了。

我 pasted 只有与 question 相关的部分,因为所有 code 太长了。


你在类定义中加入了 UICollectionViewDelegate 吗?例如:class ViewController: UIViewController, UICollectionViewDelegate - Inder Kumar Rathore
我在问题中添加了一些代码。 - Byoth
由于集合视图是一个插座 - 也就是在界面构建器中设计的 - 为什么不在IB中更方便(和可靠地)进行所有“设置”设置呢? - vadian
单元格的任何子视图都可以接收触摸事件并执行操作吗? - AechoLiu
你找到答案了吗? - Andrey Solera
显示剩余5条评论
13个回答

25

如果您的自定义单元格中有一个gestureRecognizer,则会覆盖collectionView的didSelectItemAt delegate,并导致此问题。

如果这是您遇到的问题,那么您可以通过识别gestureRecognizer并执行以下操作来解决它:

let tap = UITapGestureRecognizer(target: self, action: #selector(self.someViewInMyCellTapped(_:)))
someViewInMyCell.addGestureRecognizer(tap)

tap.cancelsTouchesInView = false

这解决了我的问题。我已经配置了Tap-, LongPress-和Pan-Gesture Recognizer,并使用一个可以淡入淡出的UICollectionView来选择东西。配置“tapRecognizer.cancelsTouchesInView = false”解决了问题,“didSelectItemAt”由委托正确调用。非常有用的答案。 - ZAY
不错的解决方案,但是你在哪里可以放置这段代码呢?如果你使用UIBuilder添加了GestureRecognizer,那么你如何在代码中识别它呢? - John Pitts

6

isUserInteractionEnabled 属性可能在 MyView 自身或其任何父级上为 false。


2
我确认它是true。我测试将UIButton添加到单元格并轻按它。它运行良好。 - Byoth
1
我的collectionViewCell上有一个ContentView(由于某些原因我无法在Xcode中删除),它启用了UserInteractive。这导致didSelectItemAt对我而言无法被调用。 - Ham Dong Kyun

4

我将Cell的子视图的isUserInteractionEnabled属性更改为false,并且它已经生效。


就是这样。简单而伟大。 - heiko

2

在我的情况下,自定义的 UITapGestureRecognizer 存在问题。尽管滚动和高亮在集合中有效,但无法进行单元格选择。我不得不使用识别器的 cancelsTouchesInView 属性。

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(myAction(_:)))
tapGestureRecognizer.cancelsTouchesInView = false // <- this helped

同时,值得注意的是,在屏幕加载完成并且视图布局完成后,检查一下你的集合视图单元格框架。


是的,但是你把这段代码放在哪里? - John Pitts
@JohnPitts 在我看来,有一个自定义的 UITapGestureRecognizer,它覆盖了我的 UICollectionView 并捕获了所有触摸。 - Savely Sakun
好的,我也一样。我也插入了cancelsTouchesInView = false,但现在我无法关闭键盘了!该死的,如果我这么做;不该死的,如果我那么做。 - John Pitts

2

如果有人和我一样遇到了Simulator XR的问题, 可以尝试使用其他模拟器。 当我在XR模拟器上使用didSelectItemAt方法时,有些索引从未被调用过,而且每次重新启动模拟器时索引都是随机的。 使用iPhone 6s模拟器可以解决这个问题。

最初的回答


1
确保该单元格是UICollectionViewCell的子类,而不是UICollectionViewReusableView

1
对我来说,问题在于我的BaseViewController上的键盘扩展。
extension NewBaseVC: UITextFieldDelegate {

    func initializeHideKeyboard(){
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(
            target: self,
            action: #selector(dismissMyKeyboard))

        view.addGestureRecognizer(tap)
    }

    @objc func dismissMyKeyboard(){
        view.endEditing(true)
    }
}

当我调用initializeKeyboard()时,TapRecognizer被触发。而且这个轻拍手势识别器与我的集合视图的didSelectItemEvent重叠了。

提醒:如果您的页面没有任何文本字段,请不要使用键盘扩展。 - Vural Çelik
对我来说也是一样的,但问题是,你如何关闭虚拟键盘呢?在键盘关闭后,如何关闭/禁用/卸载tapGestureRecognizer? - John Pitts

0

尝试在内部设置委托

func awakeFromNib(){
 super.awakeFromNib()
 self.collectionView.dataSource = self
 self.collectionView.delegate = self } 

很遗憾,它不起作用。最初只有 didSelectItemAt 不起作用。但是在按照此方法后,项目未被呈现。我猜这是因为我没有使用普通的 UIView。 - Byoth

0
在我的情况下,这是因为collectionView不停地重新加载。
collectionView.reloadData

只有在重新加载结束后,我才能与其交互。


0

还要检查父视图中的UITapGestureRecognizer

在我的情况下,UITapGestureRecognizer位于UICollectionView的一个父视图上。

UICollectionView可以正常滚动,但是didSelectItemAt从未被调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接