按下按钮时在 UITableViewCell 中查找按钮的 indexPath?

Posted

技术标签:

【中文标题】按下按钮时在 UITableViewCell 中查找按钮的 indexPath?【英文标题】:Find the indexPath of a button inside UITableViewCell when button pressed? 【发布时间】:2014-11-24 13:25:49 【问题描述】:

以下代码正确返回单元格:

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 

但在 tableview 中查找 indexpath 时会崩溃:

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

我尝试了另一种方法,但没有成功:

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)!

【问题讨论】:

【参考方案1】:

这是按钮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
        
    

还有一个:

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

【讨论】:

感谢您的快速回复,但“tableView.indexPathForRowAtPoint(point)”和“tableView.indexPathForRowAtPoint(point)”仍然返回 nil 给我。在我的例子中,'table' 通过 IBOutlet 连接,按钮是 section(TableViewCell) 的子视图【参考方案2】:

您似乎无法从处理按钮的@IBAction 的代码中找到tableView

您可以创建一个UIButton 子类来跟踪按钮所在的cell 和单元格所在的UITableView。然后在@ 中调用tableView:indexPathForCell 就很简单了987654327@ 按钮。

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)")
        
    

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

为了完成这项工作,重要的是在Identity Inspector中将UIButtonUITableViewCell 的类设置为MyButtonCustomTableViewCell。此外,在CustomTableViewCell.swift 中将按钮连接到其@IBOutlet

【讨论】:

【参考方案3】:

func findSuperView(sender:UIButton!) -> UITableViewCell 存在问题。没有任何东西可以确保foundSuperView 具有价值。

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

找到视图的超级单元格的更安全的方法是返回一个可选项。

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

如下所示。

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

【讨论】:

感谢您的快速回复,但“table.indexPathForCell(cell)”仍然返回 nil 给我。在我的例子中,“table”是通过 IBOutlet 连接的,而 button 是 section(TableViewCell) 的子视图。【参考方案4】:

如果您使用的是自定义 tableViewCell(您可能是),您可以创建一个变量。

class Cell: UITableViewCell 

    var id = ""

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

还有:

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

【讨论】:

【参考方案5】:

此代码适用于 Swift 5:

private func onTapButtonInsideCell(button: UIButton, event: UIEvent) 

    guard let touches = event.touches(for: button), !touches.isEmpty else 
        return
    

    let touch = touches[touches.startIndex]
    let point = touch.location(in: tableView)

    guard let indexPath = tableView.indexPathForItem(at: point) else 
        return
    

    print("onTapButtonInsideCell() indexPath.row=\(indexPath.row)")

Github 要点:https://gist.github.com/rsaenzi/13dc00b5cb5a09efa84eaff3ff4682af

【讨论】:

【参考方案6】:

我不知道是否有一种简单的方法可以做到这一点。 (编辑:其实是有的。看@mustafa的第二个解决方案。)一种解决方法是在cellForRowAtIndexPath中将按钮的标签设置为indexPath.row,然后你可以访问按钮的标签来找出它属于哪一行。

警告:此解决方法很脆弱。如果您允许从表中添加或删除行而不调用tableView.reloadData(),它将无法正常工作。看看@mustafa 的解决方案,它更强大。

【讨论】:

感谢您的快速回复,我应用了您的解决方案。这个对我有用。但喜欢有一个合适的替代工作解决方案。 不,如果可以添加或删除任何行,则使用基于 indexPath 的标记将不起作用。 @rmaddy。好点子。我更新了我的答案以说明这一点。由于其他答案不适用于 OP,因此我在新答案中采用了完全不同的方法。由于我的原始答案已被 OP 接受,因此我不想对其进行编辑并给人一种我的新答案已被接受的印象。

以上是关于按下按钮时在 UITableViewCell 中查找按钮的 indexPath?的主要内容,如果未能解决你的问题,请参考以下文章

按下返回按钮时在 UITextField 之间切换

帮助! uitableviewcell 按钮按下更新文本字段

按下主页按钮时在后台播放音乐

如何在按钮按下时在集合视图中滚动(水平)?

按下按钮时需要访问 UITableViewCell 的 detailTextLabel 属性

默认 UITableViewCell 状态