Expanding and Collapsing is working fine tableview, Only facing issue while didselect row is tapped, I'm getting same index evry time after selecting a row. I'm getting the same out put, I want to pass the data to next view but output isn't working properly.

Here's My Details...

My OutPut enter image description here My Model

struct ItemList {
var name: String
var items: [String]
var collapsed: Bool

init(name: String, items: [String], collapsed: Bool = false) {
     self.name = name
     self.items = items
     self.collapsed = collapsed
    }
}

My ViewController Class

class ViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!
var sections = [ItemList]()
var items: [ItemList] = [
 ItemList(name: "Mac", items: ["MacBook", "MacBook Air"]),
 ItemList(name: "iPad", items: ["iPad Pro", "iPad Air 2"]),
 ItemList(name: "iPhone", items: ["iPhone 7", "iPhone 6"])
]
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate = self
    tableView.dataSource = self
}
}

TableView Extension

extension ViewController:UITableViewDelegate,UITableViewDataSource{

 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}

  func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerHeading = UILabel(frame: CGRect(x: 5, y: 10, width: self.view.frame.width, height: 40))
let imageView = UIImageView(frame: CGRect(x: self.view.frame.width - 30, y: 20, width: 20, height: 20))
if items[section].collapsed{
    imageView.image = UIImage(named: "collapse")
}else{
    imageView.image = UIImage(named: "expand")
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60))
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(headerViewTapped))
tapGuesture.numberOfTapsRequired = 1
headerView.addGestureRecognizer(tapGuesture)
headerView.backgroundColor = UIColor.red
headerView.tag = section
headerHeading.text = items[section].name
headerHeading.textColor = .white
headerView.addSubview(headerHeading)
headerView.addSubview(imageView)
return headerView
}

func numberOfSections(in tableView: UITableView) -> Int {
  return items.count
 }

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
{
let itms = items[section]
return !itms.collapsed ? 0 : itms.items.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 
  UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
return cell
 }

@objc func headerViewTapped(tapped:UITapGestureRecognizer){
print(tapped.view?.tag)
if items[tapped.view!.tag].collapsed == true{
    items[tapped.view!.tag].collapsed = false
}else{
    items[tapped.view!.tag].collapsed = true
}
if let imView = tapped.view?.subviews[1] as? UIImageView{
    if imView.isKind(of: UIImageView.self){
        if items[tapped.view!.tag].collapsed{
            imView.image = UIImage(named: "collapsed")
        }else{
            imView.image = UIImage(named: "expand")
        }
    }
  }
   tableView.reloadData()
 }

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let row = items[indexPath.row]
    print("IndexPath :- \(row.name)")
}
}
1

There are 1 best solutions below

0
DonMag On BEST ANSWER

If you look at the way you are setting the text in your cells in cellForRowAt:

cell.textLabel?.text = items[indexPath.section].items[indexPath.row]

You are saying:

  • get the ItemList object for indexPath.section from items array
  • get the String from that object's items array of this indexPath.row

However, in your didSelectRowAt:

let row = items[indexPath.row]
print("IndexPath :- \(row.name)")

You are saying:

  • get the ItemList object for indexPath.row from items array
  • print the .name property of that object

So, change your didSelectRowAt code to match your cellForRowAt logic:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
    let selectedString = items[indexPath.section].items[indexPath.row]
    print("IndexPath :- \(selectedString)")

    // or, for a little more clarity
    let sectionObject = items[indexPath.section]
    let rowItem = sectionObject.items[indexPath.row]
    
    print("IndexPath :- \(indexPath)  //  Section :- \(sectionObject.name)  //  Item :- \(rowItem)")
    
}