PrepareForSegue from a UIButton in a custom prototype cell

一笑奈何 提交于 2019-12-06 04:11:52

You could get the index path of the cell like so

let indexPath : NSIndexPath
if let button = sender as? UIButton {
    let cell = button.superview?.superview as! UITableViewCell
    indexPath = self.tableView.indexPathForCell(cell)
}

You'll also need to change your makeSegue like this:

func makeSegue(button:UIButton) {
    self.performSegueWithIdentifier("toCoriViewController", sender: button)
}

and in your cellForRowAtIndexPath just change the line where you set the action to cell.button.addTarget(self, action: "makeSegue:", forControlEvents: UIControlEvents.TouchUpInside).

Alternatively, you could create a squadra property inside your custom cell class to hold the arrayCori value of that cell, so you'd have some code that looks like this:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
    let squadra = DataManager.sharedInstance.arrayCori[indexPath.row]
    cell.squadra = squadra #add this line
    cell.backgroundColor = UIColor.clearColor()
    if (indexPath.row % 2 == 0)
    {
        cell.backgroundColor = UIColor.greenColor()
    }
    else
    {
        cell.backgroundColor = UIColor.blueColor()
    }

    //Here I added target to the button in the cell, and below in the class I implemented the fun makeSegue()
    cell.button.addTarget(self, action: "makeSegue", forControlEvents: UIControlEvents.TouchUpInside)

    return cell
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    if segue.identifier == "toCoriViewController"
    {
        let controller = segue.destinationViewController as! CoriViewController
        if let button = sender as? UIButton {
            let cell = button.superview?.superview as! CustomCell
            controller.coriSquadra = cell.squadra
        }
    }
}

Storyboard + prepareForSegue

It can be done with just about no code by adding a separate UIStoryboardSegue with its own identifier for the button in the Storyboard.

prepareForSegue becomes:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if "fromButtonToViewController" == segue.identifier {
        if let button = sender as? UIButton {
            // ... The UIButton is the sender
        }
    }
}

This handles both tap on cell and tap on button either jointly or separately, passes the proper sender to prepare:segue:sender, thus allowing customization of the cell, the button, the transition, and ultimately the target view. The demonstration of this statement can be found in the compact project below.


► Find this solution on GitHub and additional details on Swift Recipes.

For those who are looking for a generic approach.

/* Generic function to get uitableviewcell from any UIKit controllers which stored in deep level of views or stackviews */

func getCell<T>(_ view: T) -> UITableViewCell? {

    guard let view = view as? UIView else {
        return nil
    }

    return view as? UITableViewCell ?? getCell(view.superview)
}


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    if segue.identifier == "toCoriViewController"
    {
        if let button = sender as? UIButton,
            let cell = getCell(button),
            let indexPath = tableView.indexPath(for: cell)
        {
            let controller = segue.destinationViewController as! CoriViewController
            controller.coriSquadra = DataManager.sharedInstance.arrayCori[indexPath.row]
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!