ios:在点击collectionview单元格或tableview单元格时禁用第二个触摸事件

Posted

技术标签:

【中文标题】ios:在点击collectionview单元格或tableview单元格时禁用第二个触摸事件【英文标题】:ios: disable second touch event while tapping on collectionview cell or tableview cell 【发布时间】:2019-04-22 22:03:28 【问题描述】:

我有一个带有 CollectionView 的 ViewController,它加载 ViewController 中提出的问题的四个可能答案。 当用户选择一个项目时,会调用 collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) ,其中问题会随着答案数组(始终为 4)而变化,然后调用 collectionView.reloadData 以重绘新问题并可能的答案。

一切正常,除了用户连续快速点击一个项目 2 次。 在这种情况下,第一个选择会记录答案,然后 collectionview 会再次点击(就像用户再次点击下一个问题一样)并因此回答另一个问题。

如果可能的话,我想做的是: 1.在第一次触摸时禁用触摸事件(重新加载新问题时) 2. 一旦collectionView 的reloadData 完成加载,重新启用触摸事件。这是我使用取自该线程How to tell when UITableView has completed ReloadData? 的自定义集合视图类解决的另一个问题

我尝试使用 view.userInteractionEnabled = false/true 和 UIApplication.shared.beginIgnoringInteractionEvents() 和 UIApplication.shared.endIgnoringInteractionEvents() 禁用触摸事件,但没有成功。

这是我迄今为止尝试过的:

func loadNewQuestion 
    //UIApplication.shared.beginIgnoringInteractionEvents()
    //self.view.isUserInteractionEnabled = false
    //change the question, answer, and array of possible answers
    answers = answers.shuffled() //simply shuffle the answers
    //pick a random answer
    let number = Int.random(in: 0 ... 3)
    answer = answers[number] //shuffle again and take first value


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    if stillAnswering 
        print("still answering, so skipping touch events")
        return
    
    stillAnswering = true
    print("not answering")
    let a = answers[indexPath.row]
    if a.descript.lowercased() == questionAnswer.descript.lowercased() //questionAnswer is the correct answer to the question 
        self.loadNewQuestion()
        self.collectionView.reloadData(onComplete: 
            //UIApplication.shared.endIgnoringInteractionEvents()
            //self.view.isUserInteractionEnabled = true
            stillAnswering = false
            )
     else 
        //warn about wrong answer
        stillAnswering = false
    

我已经标记了 Objective-c 和 swift,因为我不介意用于解决方案的语言,而且我相信 uitableview 与 uicollectionview 的解决方案/问题是相似的。

有什么提示吗?

【问题讨论】:

loadNewQuestion 只是简单地打乱现有数组并选择另一个随机答案.. 我还是更新了问题 【参考方案1】:

您可以在点击正确答案单元格时使用 flag 并将其设置为 true,然后在 reloadData() 的 onComplete 块中将其设置为 false。

例如:

var answerChosen: Bool = false

...

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    if answerChosen  return 

    let a = answers[indexPath.row]
    if a.descript.lowercased() == questionAnswer.descript.lowercased() //questionAnswer is the correct answer to the question 
        answerChosen = true
        self.loadNewQuestion()
        self.collectionView.reloadData(onComplete: 
            answerChosen = false    
        )
     else 
        //warn about wrong answer
    

【讨论】:

它不起作用,我已经尝试过这种方法。我更新了我的问题以反映您的更改,我得到的是 2 条印刷文本:“不回答”。我相信问题不在于跳过触摸事件。因为发生在第一次触摸和第二次触摸之间,用​​户界面正在刷新集合视图,因此操作系统正在保存第二次触摸,直到用户界面刷新并将触摸发送到无论哪个项目出现在同一位置。 您似乎错过了设置 stillAnswering = true 的行。在第二个 if 语句下尝试一下。 对不起,我忘了粘贴那部分.. 将问题编辑回来(实际上我把它放在第一个 if 语句之后,但这没关系【参考方案2】:

我终于设法解决了这个问题。解决它的技巧是将 reloadData() 放在一个调度异步块中。 这是最终代码。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    if UIApplication.shared.isIgnoringInteractionEvents 
        return //for extra safety
    
    UIApplication.shared.beginIgnoringInteractionEvents()
    let a = answers[indexPath.row]
    if a.descript.lowercased() == questionAnswer.descript.lowercased() //questionAnswer is the correct answer to the question 
        self.loadNewQuestion()
        DispatchQueue.main.async(execute: 
            self.collectionView.reloadData(onComplete: 
                UIApplication.shared.endIgnoringInteractionEvents()
            )
        )
     else 
        //warn about wrong answer
        DispatchQueue.main.async(execute: 
            self.collectionView.reloadData(onComplete: 
                UIApplication.shared.endIgnoringInteractionEvents()
            )
        )
    

【讨论】:

以上是关于ios:在点击collectionview单元格或tableview单元格时禁用第二个触摸事件的主要内容,如果未能解决你的问题,请参考以下文章

点击tableview内的collectionview单元格导航

重新排序 CollectionView 单元格 iOS 11

XCTestCase:使用 IndexPath 点击 collectionView 中的单元格

当collectionView滚动时,如何使iOS collectionView的特定单元格淡出?

collectionView:didSelectItemAtIndexPath 不会在点击时被调用

iOS 使用多个 CollectionView 重用同一个单元格