【问题标题】:Find the indexPath of a button inside UITableViewCell when button pressed?按下按钮时在 UITableViewCell 中查找按钮的 indexPath?
【发布时间】: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)!

【问题讨论】:

    标签: uitableview swift uibutton


    【解决方案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 接受,因此我不想对其进行编辑并给人一种我的新答案已被接受的印象。
          猜你喜欢
          • 2012-03-27
          • 1970-01-01
          • 2017-01-27
          • 1970-01-01
          • 2010-10-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-30
          相关资源
          最近更新 更多