I have two collectionViews CollectionViewCell
and CollectionViewCellButton
that i want to place in first and second section
of tableView respectively. I am debugging it by setting break point .
Here is my tableView.swift file cellForRowAt indexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0{
if let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcellid", for: indexPath) as? TableViewCell {
// Show SubCategory Title
(colorsArray.objectsArray[indexPath.section] as! TableViewCellModel).headerButton.setTitle("View All",for: .normal)
cell.category.text = (colorsArray.objectsArray[indexPath.section] as! TableViewCellModel).category
cell.headerButton.setTitle("View All", for: .normal)
// Pass the data to colletionview inside the tableviewcell
// debugging...
let v1 = colorsArray.objectsArray[indexPath.section]
// what is v1?
print(type(of: v1))
guard let thisTableCellModel = v1 as? TableViewCellModel else {
fatalError("Expected a TableViewCellModel !!!")
}
let v3 = thisTableCellModel.colors[indexPath.row]
// what is v3?
print("123Array=",type(of: v3)) // this is an Array, not a CollectionViewCellModel
guard let rowArray = v3 as? [CollectionViewCellModel] else {
fatalError("Expected a [CollectionViewCellModel] !!!")
}
// if we get here, we have properly unwrapped
// an array of CollectionViewCellModel
// so, don't make it an Array of Array
//cell.updateCellWith(row: [rowArray])
print("rowArray1=",type(of: rowArray))
cell.updateCellWith(row: rowArray)
cell.selectionStyle = .none
return cell
}
}
else if indexPath.section == 1{
if let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcellid", for: indexPath) as? TableViewCell {
(colorsArray.objectsArray[indexPath.section] as! TableViewCellModel).headerButton.setTitle("View All",for: .normal)
cell.category.text = (colorsArray.objectsArray[indexPath.section] as! TableViewCellModel).category
cell.headerButton.setTitle("View All", for: .normal)
// if let cell = ((colorsArray.objectsArray[indexPath.section] as! TableViewCellModel).colors as! CollectionViewCellModelButton)
// debugging...
let v1 = colorsArray.objectsArray[indexPath.section]
// what is v1?
print(type(of: v1))
guard let thisTableCellModel = v1 as? TableViewCellModel else {
fatalError("Expected a TableViewCellModel !!!")
}
let v3 = thisTableCellModel.colors[indexPath.row]
// what is v3?
print("123ArraynotNotmodel=",type(of: v3)) // this is an Array, not a CollectionViewCellModel
guard let rowArray = v3 as? [CollectionViewCellModelButton] else {
fatalError("Expected a [CollectionViewCellModelButton] !!!")
}
print("rowArray2=",type(of: rowArray))
cell.updateCellWith(row: rowArray) //break point
}
}
return UITableViewCell()
}
Here is updateCellWith
method that is called in each section
of tableView
func updateCellWith(row: [CollectionViewModel]) {
self.rowWithColors = row
self.collectionView.reloadData()
}
Here is TableViewCell.Swift file that has cellForItemAt indexPath
for collectionView
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0
{
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionviewcellid", for: indexPath) as? CollectionViewCell {
// cell.imageView = UIImage(named: (rowWithColors?[indexPath.item].image)! )
// CollectionViewCellModel
/// [CollectionViewCellModelButton
print("index1=",indexPath.section)
cell.imageView.image = (self.rowWithColors?[indexPath.item] as! CollectionViewCellModel).imageView
cell.dicountAmountLabel.text = (self.rowWithColors?[indexPath.item] as! CollectionViewCellModel).dicountAmountLabel
cell.dicountLabel.text = (self.rowWithColors?[indexPath.item] as! CollectionViewCellModel).dicountLabel
cell.customerTypeLabel.text = (self.rowWithColors?[indexPath.item] as! CollectionViewCellModel).customerTypeLabel
cell.dicountAmountLabel.textColor = .white
cell.dicountLabel.textColor = .white
cell.customerTypeLabel.textColor = .white
return cell
}
}
else if indexPath.section == 1
{
print("index2=",indexPath.section)
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionviewcellButtonid", for: indexPath) as? CollectionViewCellButton {
// cell.imageView = UIImage(named: (rowWithColors2?[indexPath.item].image)! )
//if let model = self.rowWithColors?[indexPath.item] as? CollectionViewCellModelButton {
//model.collectionButton.setTitle(model.collectionButton, for: .normal)
//cell.collectionButton.titleLabel?.text = (self.rowWithColors?[indexPath.item] as! CollectionViewCellModelButton).collectionButton.setTitle("Hi", for: .normal)
cell.collectionButton.setTitle("Hi", for: .normal)
//
return cell
}
}
return UICollectionViewCell()
}
On setting breakPoint in cell.updateCellWith(row: rowArray)
in indexPath.section == 1
of cellForRowAt indexPath
of tableView.The debugger does not enter into indexPath.section == 1
of collectionView function cellForItemAt indexPath
it revisit indexPath.section == 0
of collectionView Just for both section 0 and 1
of tableView cellForRowAt indexPath
It enter into indexPath.section == 0
of collectionView function cellForItemAt indexPath
and give run time error.How i can make it run section 1
of collectionView function on section 1
of tableView.How display both CollectionView on View ?Just like in this figure
You can download the code from this
Clearly you are holding array of CollectionViewModel
(which is a protocol) and there are two different classes that confirms to this protocol CollectionViewCellModel
and CollectionViewCellModelButton
and you blindly force cast both type to CollectionViewCellModel
using
(self.rowWithColors?[indexPath.item] as! CollectionViewCellModel).imageView
Hence the crash.
Whats the issue?
There are way too many, I'll point out few relevant in this context. Your collectionView
inside TableViewCell
always receives an array of either CollectionViewCellModel
or CollectionViewCellModelButton
(One dimensional array)
In your code you hard code number of sections as 1
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
But strangely in your cellForItemAt indexPath
you start checking indexPath.section == 0
or indexPath.section == 1
, how can indexPath.section
ever be 1 if your number of sections is hardcoded as 1?
Much more strangely you try to type cast the element in array rowWithColors
based on indexPath.section
In your code you typecast (self.rowWithColors?[indexPath.item] as! CollectionViewCellModel)
if indexPath.section == 0
and self.rowWithColors?[indexPath.item] as! CollectionViewCellModelButton
if indexPath.section == 1
What you need?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let collectionViewCellModel = self.rowWithColors?[indexPath.row] as? CollectionViewCellModel,
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionviewcellid", for: indexPath) as? CollectionViewCell {
cell.imageView.image = collectionViewCellModel.imageView
cell.dicountAmountLabel.text = collectionViewCellModel.dicountAmountLabel
cell.dicountLabel.text = collectionViewCellModel.dicountLabel
cell.customerTypeLabel.text = collectionViewCellModel.customerTypeLabel
cell.dicountAmountLabel.textColor = .white
cell.dicountLabel.textColor = .white
cell.customerTypeLabel.textColor = .white
return cell
}
if let collectionViewCellModelButton = self.rowWithColors?[indexPath.row] as? CollectionViewCellModelButton,
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionviewcellButtonid", for: indexPath) as? CollectionViewCellButton
{
//customise `CollectionViewCellButton` here with `collectionViewCellModelButton` data
return cell
}
return UICollectionViewCell()
}
O/P:
TIP:
Not sure why you have cellForItemAtIndexPath
with incorrect signature again in the same file, its good that its not getting called, but it let me wondering why? My advice, delete it :)