1

So here is the structure of the TableView: There is a main UITableView, and inside each UITableViewCell there is another UITableview

Screenshot: TableView Screenshot

Each of the UITableViewCells have been designed as Custom Views and have been added by loading it from the Nib in the cellForRowAtIndexPath function.

What I want to do is for any option selected in the inner Table Views I want to get the index path of the cell that the Table View is embeded in.

Document Layout: Document Layout

I tried to follow the delegate approach mentioned by Paulw11 here: swift: how to get the indexpath.row when a button in a cell is tapped?: StackOverflow

Note: The method suggested by Paulw11 works perfectly

Code(TableVC):

class TableVC: UITableViewController, QuestionCellDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return 5
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return 220.0
}


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

    let cell = Bundle.main.loadNibNamed("QuestionCell", owner: self, options: nil)?.first as! QuestionCell

    cell.delegate = self

    return cell
}

func sendCellInfo(cell: UITableViewCell) {

    print(cell)

    let indexPathForQuestion = tableView.indexPath(for: cell)

    print(indexPathForQuestion)
}}

Code(QuestionCell):

protocol QuestionCellDelegate: class {

func sendCellInfo(cell: UITableViewCell)
}


class QuestionCell: UITableViewCell, UITableViewDelegate,      UITableViewDataSource{

@IBOutlet weak var optionsTableview: UITableView!

var delegate: QuestionCellDelegate?

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    self.optionsTableview.delegate = self
    self.optionsTableview.dataSource = self
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

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

    let cell = Bundle.main.loadNibNamed("OptionsCell", owner: self, options: nil)?.first as! OptionsCell

    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 4
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let selectedCell = optionsTableview.cellForRow(at: indexPath)

    print("selectedCell")

        self.delegate?.sendCellInfo(cell: selectedCell!)
}}

Code(OptionsCell):

class OptionsCell: UITableViewCell {

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}}

Note: The current O/P is nil

Note: Code changed as per commented by pbasdf, realised the mistake

Community
  • 1
  • 1
Supratik Majumdar
  • 2,365
  • 1
  • 23
  • 31
  • I don't know why are you following this approach, I would suggest you to go with simple UITableView with Section(Question title) & each section has specific number of cells(options). Using this approach you can easily handle the above case. Just saying as per my understanding of the above case, Please ignore if it didn't satisfy your need. – Bharath Oct 25 '16 at 12:38
  • @Bharath Yes, that is a much more easier approach and even better design wise. But, I want to know how this can be done. And if you how. – Supratik Majumdar Oct 25 '16 at 16:01
  • 1
    You are using the delegate design pattern in the wrong place. Your `QuestionCell` should define the protocol and have the `delegate` property that conforms to it. Your `TableVC` should adopt the protocol and implement the corresponding method (and, in `cellForRowAt:` set the cell `delegate` property to self). The `didSelectRowAt` method in `QuestionCell` should then call the protocol method on `self.delegate?`. – pbasdf Oct 25 '16 at 23:13
  • @pbasdf: You were right. Thank for the same. I did make the changes, but now the O/P I get is nil – Supratik Majumdar Oct 26 '16 at 10:26
  • @SupratikMajumdar Try `self.delegate?.sendCellInfo(cell: self)` instead of `self.delegate?.sendCellInfo(cell: selectedCell!)` (ie the QuestionCell, not the OptionCell). – pbasdf Oct 26 '16 at 13:17
  • @SupratikMajumdar: I have added the code as you asked in the answer section since its little big. If it satisfies your need please close the issue by choosing the answer. – Bharath Oct 26 '16 at 15:01
  • @pbasdf Got the answer, refer below. Thanks to your previous comment – Supratik Majumdar Oct 26 '16 at 15:12
  • @Bharath Thanks for your answer, but I was able to figure out the way I actually intended to – Supratik Majumdar Oct 26 '16 at 15:16
  • @SupratikMajumdar: Thats great. – Bharath Oct 27 '16 at 03:42

3 Answers3

1

Found the solution due to pbasdf comment:

Delegate Function in TableVC:

 func sendCellInfo(cell: UITableViewCell) {

    /*** Take the cell passed and convert to a CGPoint wrt to TableView ***/
    let cellPosition: CGPoint = cell.convert(cell.bounds.origin, to: self.tableView)

     /*** wrt to CGPoint find index on current TableView ***/
    /*** Returns as Section,Cell ***/
    let indexPathForSelectedCell = (tableView.indexPathForRow(at: cellPosition)?.row)

    print(indexPathForSelectedCell)
}
Supratik Majumdar
  • 2,365
  • 1
  • 23
  • 31
0

Use this:

tableView.cellForRowAtIndexPath(YourIndexPath) as! OptionCell

You can do your own indexPath as global variable and filing it on didSelectRow method

YourIndexPath = indexPath

Lucas Palaian
  • 374
  • 2
  • 12
0

The following answer is added @Supratik Majumdar request for the logic which I said.

Supratik try using the following code, I hope you will get your need done.

//Initialize your question or answer in viewDidLoad or where ever you like to as shown below
self.questionArray = ["Question1", "Question2"]
self.optionArray = [["Option 1", "Option 2", "Option 3", "Option 4"], ["Option 1", "Option 2", "Option 3", "Option 4"]]


//Make us of the following tableview delegate & datasource code
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.questionArray.count
    }

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.OptionArray[section].count
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
    return self.questionArray[section]
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell

    let currentOptionArray = self.questionArray[section]
    let currentOption = currentOptionArray[indexPath.row]

    cell.textLabel.text = currentOption

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedIndex = indexPath
    let selectedQuestionIndex = indexPath.section
    let selectedOptionIndex = indexPath.row

    //Make use of the data you need in the above values
}
Bharath
  • 2,064
  • 1
  • 14
  • 39