未调用 UIcollectionView 的 didDeselectItemAt 但调用了 didSelectItemAt?

Posted

技术标签:

【中文标题】未调用 UIcollectionView 的 didDeselectItemAt 但调用了 didSelectItemAt?【英文标题】:didDeselectItemAt For UIcollectionView is not called but didSelectItemAt is called? 【发布时间】:2019-12-10 18:54:26 【问题描述】:

我正在尝试为 UICollectionView 实现多选。委托函数 didSelectItemAt 被调用,但 didDeselectItemAt 从未被调用,我不知道为什么?我什至不确定它是如何工作的。如果我点击一个单元格 - didSelectItemAt 被调用。因此,如果我再次单击同一个单元格,是否应该调用 didDeselectItemAt?

我的 UIViewController 继承并符合以下所有内容:UICollectionViewDelegate、UICollectionViewDataSource、UICollectionViewDelegateFlowLayout

viewdidLoad():

collectionView.allowsSelection = true
collectionView.allowsMultipleSelection = true

委托功能:

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    print("didSelectItemAt")



func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) 
    print("DESELECT")

【问题讨论】:

这就是 didSelect 的功能。当您选择另一个单元格时,将调用 didDeselect。您所要求的必须是自定义实现的 @GaloTorresSevilla - 感谢您的回复。但在这种情况下,“didDeselectItemAt”永远不会调用我点击的任何内容。 @matt - 下面的答案似乎与你所说的相矛盾。我只是不知道为什么没有调用委托函数 'didDeselectItemAt' 尽管allowsMultipleSelection设置为'true'(即使调用了didSelectItemAt) 【参考方案1】:

请在 Github 上查看 this 公开问题。

可能是您在包含您的集合视图的同一层次结构中的视图上有一个点击手势识别器。删除点击手势,看看是否有效。这恰好是我的问题。

let tap = UITapGestureRecognizer(...) // your tap gesture recognizer
view.addGestureRecognizer(tap) // what you already have
tap.cancelsTouchesInView = false

【讨论】:

这是一个非常令人沮丧的问题,这可能就是我被否决的原因 - 但是,在至少多次面对这个问题之后,很明显这是一个常见问题,我发布的解决方案是有据可查的 您的答案主要涉及didSelectItemAt 未被调用,而OP 的问题是关于didDeselectItemAt 未被调用。但是,我相信在这种情况下,您的回答可能会帮助那些被这两个电话困住的人。【参考方案2】:

我猜测您的代码与您向我们展示的代码不同,并且在您的真实代码中,您没有为didDeselect 提供正确的签名。这就是为什么。仔细查看您显示的代码:

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    print("didSelectItemAt")



func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) 
    print("DESELECT")

现在问问你自己:为什么编译器允许第二个 func 存在,即使你忘了说 override?我猜这是因为它 不是 覆盖。签名有问题,所以只是一个不符合UICollectionViewDelegate的无意义函数。

尝试使用代码完成重新进入该函数。如果一切顺利,它将被覆盖并开始工作。


为了更准确地说明:这会编译,但永远不会调用第二个方法:

class CV : UICollectionViewController 
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
        print("didSelectItemAt")
    
    func colectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) 
        print("DESELECT")
    

但这并不能编译,因为签名是正确的但我们忘记了override

class CV : UICollectionViewController 
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
        print("didSelectItemAt")
    
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) 
        print("DESELECT")
    

但是在第二个中,如果我们override,它会编译并且工作

【讨论】:

天哪。这是因为没有 OVERRIDE。学过的知识。非常感谢。 但是,正如我所说,如果没有override,您的代码一开始就不应该编译;如果是这样,我不明白为什么。 我认为它编译是因为我的 UICollectionView 是自定义的,它是我编写的 UICollectionView 的自定义通用类的子类。为了解决这个问题,我将 didDeselectItemAt 函数添加到我的 UICollectionView 通用类中,然后将覆盖添加到我实际使用的子类中(上图)。所以在修复之前,我的 Generic 类没有 didSelectItemAt,通过子类化并忘记添加覆盖,它编译了.... OP 有一个实现UICollectionViewDelegateUIViewController 而不是UICollectionViewController,因此无需添加override。 (并且会触发编译器错误,因为没有什么可以覆盖。) @JasonMoore 不,因为对于 OP override func collectionView(_ collectionView: UICollectionView, didSelectItemAt 确实 编译。不一致揭示了问题的真正根源,OP 直到后来的评论才揭露。缺陷在于 OP 自己的通用子类,我们在原始问题中没有被告知。【参考方案3】:

它是这样工作的:

如果collectionView.allowsMultipleSelection = false // 默认,那么您必须点击不同的单元格才能取消选择前一个单元格。

if collectionView.allowsMultipleSelection = true // 仅点击相同单元格触发取消选择委托方法

【讨论】:

解释清楚,非常有意义。但是我已经对此进行了测试,但是从不调用 didDeselectItemAt(调用了didSelectItemAt)......即使collectionView.allowsMultipleSelection = true。你知道为什么会这样吗?【参考方案4】:

我不确定这是否最近发生了变化,但在 ios13 中,似乎仅指定在单元格出列时选择集合视图单元格并不足以让集合视图允许您取消选择单元格。您还需要手动告诉集合视图选择单元格。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: photoCellIdentifier, for: indexPath) as! YourCell
    cell.isSelected = true
    if cell.isSelected 
        collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .left)
    

我知道这一点是因为我能够选择和取消选择单元格,但无法取消选择最初选择的单元格。

【讨论】:

以上是关于未调用 UIcollectionView 的 didDeselectItemAt 但调用了 didSelectItemAt?的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 未显示 & 未调用委托/数据源方法

未调用 UICollectionView cellForItem

未调用 UICollectionView 内部 UITableView 的委托方法

未调用 TableViewCell 内的 UICollectionView

UICollectionView shouldShowMenuForItemAt 未调用

未调用 UIScrollView 内的 UICollectionView 的 didSelectItemAtIndexPath