UICollectionView 中的两个 UITableView 使用相同的引用?

Posted

技术标签:

【中文标题】UICollectionView 中的两个 UITableView 使用相同的引用?【英文标题】:two UITableView in a UICollectionView using the same reference? 【发布时间】:2019-10-24 12:30:18 【问题描述】:

我有一个 UICollectionView,里面有 4 个视图。这些视图中的每一个都有一个带有自定义单元格的 UITableView。 UITableView 的每个单元格内部都有一个 UIButton,每个 UITableView 有 2 个单元格。

发生了一些奇怪的事情。我对每个按钮都有一个动作功能,这样当一个按钮被点击时,它就会变成紫色。奇怪的是:如果我滚动到收藏视图的第 4 个视图并单击一个按钮,它会按预期变为紫色,但是当我滚动到收藏视图的第一个视图时,与我在第四个视图(第一个或第二个)也是紫色的,好像我的集合视图的第四个视图引用了我的集合视图的第一个视图的项目。

我不知道第一个视图在什么时候与第四个视图相同,但这里是代码示例:

// this is the cellForItemAt of my UICollectionView, very basic
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cellView = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! PollCellView
        return cellView
    

// THIS IS ANOTHER FILE HERE
// this is part of my view that populate the UICollectionViews
class PollCellView: UICollectionViewCell 

    // the table view
    let questAndAnswersTableView : UITableView = 
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.separatorStyle = .none
        tableView.allowsSelection = false
        return tableView
    ()

// I add the tableview in the view here
override init(frame: CGRect) 
        super.init(frame: frame)
        addSubview(questAndAnswersTableView)


// a classic cellForRowAt of my UITableView
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "AnswerCell2", for: indexPath) as! AnswerCell2
        return cell
    


// THIS IS ANOTHER FILE HERE
// this part is my custom cell of the UITableView
class AnswerCell2: UITableViewCell 

    let answerTextButton: UIButton = 
        let answerButton = UIButton()
        answerButton.setTitle("initial text", for: .normal)
        return answerButton
    ()

// I add the button to the cell here
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String!) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        addSubview(answerTextButton)
        // I define the action function
        answerTextButton.addTarget(self, action: #selector(answerClicked), for: .touchUpInside)


// the action to make the button purple
@objc func answerClicked(sender: UIButton) 
        sender.backgroundColor = UIColor(displayP3Red: 0.6902, green: 0.7176, blue: 0.9922, alpha: 1.0)

[根据收到的答案进行编辑]

出队绝对不像最初看起来那么简单...您不能相信在给定集合视图中出队的表格视图确实是您所期望的...您需要跟踪内容(模型)你自己。更容易修复的一件事是在 TableView 的单元格和 UICollectionViewCell 的单元格之间使用闭包......您可以非常轻松地将数据从一个传递到另一个(例如单击了什么 indexPath 等)。

【问题讨论】:

【参考方案1】:

当您管理多个嵌套的 tableviews 或 collectionviews 时,甚至当您自己管理它时,您必须设置一个数组系统,当单击按钮时,您将这些索引路径添加到一个名为“indexPathsThatArePuple”的数组中然后,当您在每次单击按钮后,在按钮单击功能内,传递 indexPath 并将其添加到数组中。如果按下按钮单击功能时按钮已经在数组中,则删除该 indexPath。在按钮单击功能中,添加或删除 indexPaths 后,重新加载将重新加载 tableviews 的集合视图,然后在“cellForItemAtIndexPath”中检查 indexPathsThatArePuple 数组,然后写入“如果 indexpath 包含在 indexPathsThatArePuple 中”,然后设置单元格颜色变成紫色。

我了解您想要做什么,但您没有意识到或不了解 ios 中的单元重用系统有多复杂。您需要做的第一件事是围绕这样一个想法,即由于单元重用,您必须手动管理单元状态。另一个表中显示的紫色单元格来自单元格重用。 Apple 不会自动为您管理,您必须自己完成。正如我上面所描述的,甚至我上面的描述也不是那么简单,因为在你掌握这个概念之前,你可能会为此挣扎数周。祝你好运,你最终会得到它。

【讨论】:

可能这是一个很好的答案,但很难说。您应该考虑改进格式,例如句子开头的大写字母,一些空格,以及带有monospacing 反引号的类/func/var 名称的正确大小写,例如UITableView 而不是 tableview 还要考虑添加一些(伪)代码示例而不是散文。这看起来像是一种难以解析的“意识流”。 谢谢,我设法通过跟踪模型中的数据来修复它,可能以丑陋的方式完成了它,但它现在正在工作。【参考方案2】:

似乎是 UICollectionView 单元重用机制造成的。

当单元格被创建并滚动出屏幕时,如果需要具有相同标识符的新单元格,它将在以后重复使用。在你的情况下,当你向下滚动时,第一个视图被重用为第四个视图,当你滚动到顶部时,第四个视图被重用为第一个视图。如果prepareForReuse方法没有实现,单元格的UI状态不会改变,所以你会看到紫色的按钮。

【讨论】:

也感谢您的回答,当我回答另一个答案时,我设法通过一个数组来修复它,该数组根据状态强制模型值(包括按钮的颜色)。所以这确实是问题所在。我没有使用 prepareForReuse 但我会看看它,因为它似乎也是一个好主意,我现在把所有东西都放在 cellForItemAt 中。

以上是关于UICollectionView 中的两个 UITableView 使用相同的引用?的主要内容,如果未能解决你的问题,请参考以下文章

一个 UIViewController 中的两个 UICollectionView

UICollectionView 中的两个 UITableView 使用相同的引用?

我想在所有 iphone 型号的 uicollectionview 中的一行中显示两个单元格

MySQL 中的视图性能

两个 UICollectionView 的初始化和切换

在两个 UICollectionView 之间拖放