Reputation: 161
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.
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.
Upvotes: 1
Views: 1511
Reputation: 285039
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
}
Upvotes: 0
Reputation: 14030
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.
Upvotes: 0