简体   繁体   中英

How to get an array of arrays inside of UICollectionView that's inside a UITableView and also return the correct number of items?

I am currently trying to figure out how to get a UITableView with a UICollectionView to show the following data set correctly inside the 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"]]

I have the headers looking working fine as seen below.

屏幕截图1

However, when I scroll horizontally inside the UICollectionViews, the data will get all messed up. This can be seen in both the above and below screenshots because I scrolled in the top UICollectionView.

在此处输入图片说明

Here is the following code.

ViewController

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()
    }
}

Finally, the TableViewCell file that is populating the UICollectionView data.

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
    }
}

As you can also see in the code directly above I am also having an issue with displaying the correct amount of items in section for the UICollectionView.

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

The 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"]]

...can end up having more data then what is currently given. For example, index 0 in this array could have 4 instead of its current 3.

To recap, I am having trouble displaying the data in the collection view cells as well as setting the number of items per section in a way that would automatically adjust if more data was added.

Thank you for your time, I really appreciate it.

You are dealing with an object oriented language. Take advantage of it and use a custom struct

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"])]

...

As an example these are the table view related delegate methods. The collection view equivalents are very similar

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
}

Because of cell reusing you have to reload the collection view when a table view cell is dequeued:

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()
}

Apart from that, you should also consider vadian 's answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM