Simone Simone -4 years ago 162
iOS Question

CollectionView inside Tableview, error with datasource

i have a uiviewcontroller, where i put a uitableview, with custom cells. Each of these cells, have inside a uicollectionview, with a horizontal scrolling.

I am working programmatically, so the tableviewcell is the delegate/datasource for collectionview.

My datasource structure, is an array of arrays.

My tableview, has, for every tableviewcell, a tableview section.Tableview datasource methods work without problem using the array. I am able to set up the tableview correctly.
Inside this cell, i want to display a collectionview, with horizontal scrolling.

The problem which i am encountering is i cannot assign datasource correctly using the arrays to collectionview. What happens is when i load the tableview, and scrolling down, i see duplicate records, so for example the first 3 rows are displayed correctly(in terms of data and number of items),but from the 4th row, for example, data is duplicated, so i see again the records for the first 3 rows, and of course this does not have to happen, because if i scroll on the 4th line(the collectionview on the 4th row) the app crashes due to an index problem out of range.

This is simple to understand: lets say i have 10 cells on the first row, and 5 on the 4th row/or section, as you prefer... Scrolling the 4th row'scollection view will cause the crash. This is because of the wrong data which is actually the same from the first row: instead, i have only 5 cells to render...

Tecnique i am using is pretty simple: give each tableviewcell's tag the actual indexpath.section. Then in the collectionview, use this tag to loop through array and then the indexpath.item to get the correct array.

Lets get a look into the code now:

Tableview

func numberOfSections(in tableView: UITableView) -> Int {
return DataManager.shared.datasource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! DiarioTableViewCell
cell.tag = indexPath.section

return cell
}


TableviewCell

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: "cell")

collectionView.register(DiarioCVCell.self, forCellWithReuseIdentifier: "cellCV")
collectionView.delegate = self
collectionView.dataSource = self

DataManager.shared.istanzaCV = self.collectionView

addSubview(tableCellBG)
addSubview(collectionView)
setConstraints()
}


CollectionView

func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

let tvCell = collectionView.superview as! DiarioTableViewCell
return DataManager.shared.datasource[tvCell.tag].count

}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellCV", for: indexPath) as! DiarioCVCell

let celltag = (collectionView.superview as! DiarioTableViewCell).tag

cell.datasource = DataManager.shared.datasource[celltag][indexPath.item]

return cell
}


Notice i have read all the possibly related threads, even ashfurrow's article, and here on stack, but i was not able to find a solution.
Thanks for any help!

Answer Source

Try to reload your collection view when cell is showing. Cells are being reused to save memory so they are created only once - you are setting all data at init and it's staying there forever.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! DiarioTableViewCell
    cell.tag = indexPath.section
    cell.collectionView.reloadData()
    cell.collectionView.collectionViewLayout.invalidateLayout() //just to be sure, maybe it's not necessary

    return cell
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download