1

My TableView features custom Cells which have a button to display corresponding detailed info in another view. This thread here got me started and I tried to implement the approach with the delegate inside the customCell: How to access the content of a custom cell in swift using button tag?

What I want to achieve is that when I click on the button it reads the name of the cell and passes it on to the next controller. However it seems that I cannot pass the name with the delegate method and its field is nil.

How can I get the specific content of a cell when clicking on its button?

This is what I did so far:

In the class creating my own cell I set delegate:

protocol CustomCellDelegate {
 func cellButtonTapped(cell: DemoCell)
}
(........)
 var delegate: CustomCellDelegate?

@IBAction func buttonTapped(sender: AnyObject) {
    delegate?.cellButtonTapped(self)
}

In the TableViewController I have the following:

 override func tableView(tableView: UITableView, cellForRowAtIndexPath
    indexPath: NSIndexPath) -> UITableViewCell {
    let cell =
        tableView.dequeueReusableCellWithIdentifier("FoldingCell",
                                                    forIndexPath: indexPath) as! DemoCell
    cell.delegate = self

 //TODO: set all custom cell properties here (retrieve JSON and set in cell), use indexPath.row as arraypointer

    let resultList = self.items["result"] as! [[String: AnyObject]]
    let itemForThisRow = resultList[indexPath.row]

    cell.schoolNameClosedCell.text = itemForThisRow["name"] as! String
    cell.schoolNameOpenedCell.text = itemForThisRow["name"] as! String

    self.schoolIdHelperField = itemForThisRow["name"] as! String

    cell.schoolIntroText.text = itemForThisRow["name"] as! String

  //call method when button inside cell is tapped
    cell.innerCellButton.addTarget(self, action: #selector(MainTableViewController.cellButtonTapped(_:)), forControlEvents: .TouchUpInside)

    cell.school_id = itemForThisRow["name"] as! String

  //  cell.schoolIntroText.text = "We from xx University..."
    return cell
}

And finally the target method when the button inside the cell is clicked

func cellButtonTapped(cell: DemoCell) {
    print("the school id: ")
    print(cell.schoolNameOpenedCell) //this line throws an error EXC_BAD_ACCESS 0x0

}
Community
  • 1
  • 1
Stefan Badertscher
  • 331
  • 1
  • 6
  • 20

2 Answers2

3

Firstly, the object innerCellButton is not a Cell, it's a button. The simple way to solve your problem is, just refer the index of the button. Please find the below method.

func cellButtonTapped(AnyObject: sender) {

  let resultList = self.items["result"] as! [[String: AnyObject]]
  //Get the tag value of the selected button. 
  //Button tag should be matching with the corresponding cell's indexpath.row
  let selectedIndex = sender.tag
  let itemForThisRow = resultList[selectedIndex]
  print("the school id: \(itemForThisRow[\"name\"])")

}

* And set each button's tag as indexPath.row *

E.g.,

override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {

// Dequeue your cell and other code goes here.

// set the button's tag like below.
cell.innerCellButton.tag = indexPath.row
return cell
}
Suresh Kumar Durairaj
  • 2,104
  • 16
  • 24
  • Thx, this is working well. I had to change the protocol signature: protocol CustomCellDelegate { func cellButtonTapped(cell: DemoCell) to (sender: AnyObject) } and func cellButtonTapped(AnyObject: sender) to func cellButtonTapped( sender: AnyObject) – Stefan Badertscher Jul 19 '16 at 01:51
0

Close. I wouldn't use Suresh's method since it does not help find the IndexPath, which includes section and row.

First, I would recommend a model object for your table view data source. Learn more about the MVC pattern as well as parsing a JSON response to an object with mapping. However, this would give you the data you want.

func cellButtonTapped(cell: UITableViewCell) {
    let indexPath = tableView.indexPathForCell(cell)
    let resultList = self.items["result"] as! [[String: AnyObject]]
    let itemForThisRow = resultList[indexPath.row]
    let name = itemForThisRow["name"] as! String
}
Andy
  • 750
  • 7
  • 23