按下按钮时在 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中将UIButton
和UITableViewCell
的类设置为MyButton
和CustomTableViewCell
。此外,在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?的主要内容,如果未能解决你的问题,请参考以下文章
帮助! uitableviewcell 按钮按下更新文本字段