如何在 UITableView 内的 UICollectionView 内获取数组数组并返回正确数量的项目?

Posted

技术标签:

【中文标题】如何在 UITableView 内的 UICollectionView 内获取数组数组并返回正确数量的项目?【英文标题】:How to get an array of arrays inside of UICollectionView that's inside a UITableView and also return the correct number of items? 【发布时间】:2019-03-28 08:45:06 【问题描述】:

我目前正在尝试弄清楚如何使用 UICollectionView 获取 UITableView 以在 UICollectionViews 中正确显示以下数据集。

[["food 1", "food 2", "food 3"], ["car 1", "car 2", "car 3", "car 4"], ["house 1", "house 2"], ["person 1", "person 2", "person 3", "person 4"], ["kid 1", "kid 2", "kid 3", "kid 4", "kid 5"]]

我的标题看起来工作正常,如下所示。

但是,当我在 UICollectionViews 中水平滚动时,数据会变得一团糟。这可以在上面和下面的屏幕截图中看到,因为我在顶部 UICollectionView 中滚动。

下面是代码。

视图控制器

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 
    @IBOutlet weak var tableView: UITableView!

    let section = ["foods","cars","houses","persons","kids"]

    override func viewDidLoad() 
        super.viewDidLoad()
        tableView.estimatedRowHeight = 122
        tableView.tableFooterView = UIView()
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
        return self.section[section]
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return section.count
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 1
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        if let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as? TableViewCell
        
            data = [["food 1", "food 2", "food 3"], ["car 1", "car 2", "car 3", "car 4"], ["house 1", "house 2"], ["person 1", "person 2", "person 3", "person 4"], ["kid 1", "kid 2", "kid 3", "kid 4", "kid 5"]][indexPath.section]

            return cell
        
        return UITableViewCell()
    

CollectionViewCell

class CollectionViewCell: UICollectionViewCell 
    @IBOutlet weak var dataLabel: UILabel!
    override func awakeFromNib() 
        super.awakeFromNib()
    

最后是填充 UICollectionView 数据的 TableViewCell 文件。

var data = [String]()

class TableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 

    @IBOutlet weak var collectionView: UICollectionView!

    let collCount = Int()
    //var imageArray = [[String]] ()
    override func awakeFromNib() 
        super.awakeFromNib()
        self.collectionView.delegate = self
        self.collectionView.dataSource = self

    
    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return 1
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 3 //should return the amount of data per array
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        if let cell: CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? CollectionViewCell
        

            cell.dataLabel.text = data[indexPath.item]

            return cell
        
        return UICollectionViewCell()
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
        let size = CGSize(width: 256, height: 100.5)
        return size
    

正如您在上面的代码中看到的那样,我在 UICollectionView 部分中显示正确数量的项目时也遇到了问题。

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 3 //should return the amount of data per array in the array of data
    

数据...

[["food 1", "food 2", "food 3"], ["car 1", "car 2", "car 3", "car 4"], ["house 1", "house 2"], ["person 1", "person 2", "person 3", "person 4"], ["kid 1", "kid 2", "kid 3", "kid 4", "kid 5"]]

...最终可能会获得比当前给出的更多的数据。例如,此数组中的索引 0 可能有 4 而不是当前的 3。

回顾一下,我无法在集合视图单元格中显示数据以及设置每个部分的项目数,如果添加更多数据会自动调整。

感谢您的宝贵时间,我真的很感激。

【问题讨论】:

【参考方案1】:

由于单元格重用,当表格视图单元格出列时,您必须重新加载集合视图:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as? TableViewCell
    
        data = [["food 1", "food 2", "food 3"], ["car 1", "car 2", "car 3", "car 4"], ["house 1", "house 2"], ["person 1", "person 2", "person 3", "person 4"], ["kid 1", "kid 2", "kid 3", "kid 4", "kid 5"]][indexPath.section]
        cell.collectionView.reloadData()

        return cell
    
    return UITableViewCell()

除此之外,你还应该考虑vadian的回答。

【讨论】:

【参考方案2】:

您正在处理一种面向对象的语言。利用它并使用自定义结构

struct Section 
    let title : String
    let items : [String]


class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

    let sections = [Section(title: "foods", items: ["food 1", "food 2", "food 3"]),
        Section(title: "cars", items: ["car 1", "car 2", "car 3", "car 4"]),
        Section(title: "houses", items: ["house 1", "house 2"]),
        Section(title: "persons", items: ["person 1", "person 2", "person 3", "person 4"]),
        Section(title: "kids", items: ["kid 1", "kid 2", "kid 3", "kid 4", "kid 5"])]

...

例如,这些是与表视图相关的委托方法。集合视图等价物非常相似

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    return sections[section].title


func numberOfSections(in tableView: UITableView) -> Int 
    return sections.count


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return sections[section].items.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    // force unwrap the cell. Any crash reveals a design mistake
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! TableViewCell
    let section = sections[indexPath.section]
    cell.dataLabel.text = section.items[indexPath.row]
    return cell

【讨论】:

但是如果我正在解析 API 或者用户要添加新项目的另一个部分怎么办?所以不是食物、汽车、房子、人和孩子;它将是食物、汽车、房屋、人、孩子和笔记本电脑。笔记本电脑也有自己的一套物品。我怎样才能让你的“让部分”根据数组响应的数组自动更新? @Ron 这是虚拟数据,该部分将是您的 API 模型,因此它是动态的,您无需担心。 当然你可以动态填充数据源。将 sections 声明为 var 并附加项目或将 API 响应直接映射到 Section 项目。根据数据模型,而不是数组数组将数据作为 JSON 字典数组发送。 忽略节标题。我只是真的在尝试 API 数据([[“food 1”,“food 2”,“food 3”],[“car 1”,“car 2”,“car 3”,“car 4”],[ “房子 1”、“房子 2”]、[“人 1”、“人 2”、“人 3”、“人 4”]、[“孩子 1”、“孩子 2”、“孩子 3”、“ child 4", "kid 5"]] ) 到 UICollectionView 单元格中。但是,此响应可以在数组内部包含更多数组,并且可以在数组内部包含更多数组。我只是不知道如何获取数据以正确填充集合视图。我提供的数据被替换为虚拟数据,但它的格式与我从 api 接收它的方式完全相同。 我只是不太明白,抱歉。

以上是关于如何在 UITableView 内的 UICollectionView 内获取数组数组并返回正确数量的项目?的主要内容,如果未能解决你的问题,请参考以下文章