Find the indexPath of a button inside a UITableViewCell on button click?

The code below returns the cell correctly:

func findSuperView(sender:UIButton!) -> UITableViewCell { 
    var superView : UIView? = sender.superview 
    var foundSuperView : UITableViewCell! 

    while superView != nil && foundSuperView == nil { 
        if let cell = superView as? UITableViewCell { 
            foundSuperView = cell 
            break 
        } 
        else { 
            superView = superView?.superview 
        } 
    } 
    return foundSuperView 
}

      

But for looking up indexpath in tableview it fails:

var indexPath : NSIndexPath = self.table .indexPathForCell(findSuperView(sender))!
println("Section (indexPath)")

      

And I tried another way, but it failed:

var button : UIButton = sender as UIButton; 
var touch: UITouch = events .allTouches()?.anyObject() as UITouch 
var location : CGPoint = touch.locationInView(self.table) 
var indexPath : NSIndexPath = self.table.indexPathForRowAtPoint(location)!

      

+3


source to share


5 answers


I don't know if there is an easy way to do this. ( Edit: Actually there is. Have a look at @ mustafa's second solution.) The workaround is to set the button tag indexPath.row

to cellForRowAtIndexPath

, then you can just access the button tag to find out which row it belongs to.



Warning: This workaround is fragile. It will not work correctly if you allow adding or removing rows from the table without calling tableView.reloadData()

. Have a look at @mustafa's solution which is much more robust.

0


source


Below is the candidate action method for your button TouchUpInside

.

func someAction(sender:UIButton, event: UIEvent) {
    if let touch = event.touchesForView(sender)?.anyObject() as? UITouch {
        let point = touch.locationInView(tableView)
        if let indexPath = tableView.indexPathForRowAtPoint(point) {
            // Do something with indexPath
        }
    }
}

      



And here's another one:

func someAction(sender: UIButton) {
    let point = tableView.convertPoint(CGPointZero, fromView: sender)
    if let indexPath = tableView.indexPathForRowAtPoint(point) {
        // Do something with indexPath
    }
}

      

+10


source


You seem to be having trouble finding tableView

from your code that handles @IBAction

for your button.

You can create a subclass UIButton

that keeps track of both the button cell

and the button UITableView

that the cell belongs to. Then a simple call to tableView:indexPathForCell

in @IBAction

for a button.

MyButton.swift:

class MyButton: UIButton {
    weak var myTable: UITableView?
    weak var myCell:  UITableViewCell?
}

      

CustomTableViewCell.swift:

class CustomTableViewCell: UITableViewCell {
    @IBOutlet weak var myButton: MyButton!

    @IBAction func whereAmI(button: MyButton) {
        if let myCell = button.myCell, indexPath = button.myTable?.indexPathForCell(myCell) {
            print("I am in row \(indexPath.row)")
        }
    }
}

      

In TableViewController.swift:

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

    cell.myButton.myCell = cell
    cell.myButton.myTable = tableView

    // Other cell setup

    return cell
}

      

To get this work done, it is important to set the classes for UIButton

both UITableViewCell

in MyButton

and CustomTableViewCell

in the Identity inspector. In addition, connect the button to the @IBOutlet

in CustomTableViewCell.swift

.

+1


source


There was a problem with func findSuperView(sender:UIButton!) -> UITableViewCell

. Nothing guarantees that it foundSuperView

will matter.

func findSuperView(sender:UIButton!) -> UITableViewCell { 
    var superView : UIView? = sender.superview 
    var foundSuperView : UITableViewCell! // NOTE: The value is nil.

    while superView != nil && foundSuperView == nil { 
        if let cell = superView as? UITableViewCell { 
            foundSuperView = cell 
            break 
        } 
        else { 
            superView = superView?.superview 
        } 
    } 
    return foundSuperView // NOTE: This will crash if foundSuperView == nil
}

      

A safer way to search for a view supercell returns an optional.

func findSuperCellOfView(view: UIView?) -> UITableViewCell? {
    if view == nil {
        return nil
    } else if let cell = view as? UITableViewCell {
        return cell
    } else {
        return findSuperCellOfView(view?.superview)
    }
}

      

which will be used as follows.

if let cell = findSuperCellOfView(button) {
    let indexPath = table.indexPathForCell(cell)
    println("Section \(indexPath)")
}

      

0


source


If you are using a custom tableViewCell (which you probably are), you can simply create a variable.

class Cell: UITableViewCell {

    var id = ""

    @IBAction func buttonPressed(sender: AnyObject) {
        print(id) // Can also call a function with 'id' as a parameter
    }
}

      

and

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

    cell.id = indexPath.row // Or however you wan't to give it an Id

    return cell
}

      

0


source







All Articles