Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按下按钮时,是否在UITableViewCell中查找按钮的indexPath?_Uitableview_Swift_Uibutton - Fatal编程技术网

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

按下按钮时,是否在UITableViewCell中查找按钮的indexPath?,uitableview,swift,uibutton,Uitableview,Swift,Uibutton,下面的代码正确返回单元格: func findSuperView(sender:UIButton!) -> UITableViewCell { var superView : UIView? = sender.superview var foundSuperView : UITableViewCell! while superView != nil && foundSuperView == nil { if let cell

下面的代码正确返回单元格:

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

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


警告:此解决方案很脆弱。如果允许在不调用
tableView.reloadData()
的情况下从表中添加或删除行,则无法正常工作。看看@mustafa的解决方案,它更加健壮。

func findSuperView(发送方: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)")
}

下面是按钮的
触碰内部事件的候选操作方法

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
    }
}

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

您可以创建一个
UIButton
子类来跟踪按钮所在的
单元格和单元格所在的
UITableView
。然后,只需在
@IBAction
中调用按钮的
tableView:indexPathForCell

MyButton.swift:

class MyButton: UIButton {
    weak var myTable: UITableView?
    weak var myCell:  UITableViewCell?
}
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)")
        }
    }
}
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
}
CustomTableViewCell.swift:

class MyButton: UIButton {
    weak var myTable: UITableView?
    weak var myCell:  UITableViewCell?
}
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)")
        }
    }
}
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
}
在TableViewController.swift中:

class MyButton: UIButton {
    weak var myTable: UITableView?
    weak var myCell:  UITableViewCell?
}
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)")
        }
    }
}
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
上。如果您使用的是自定义tableViewCell(可能是),则只需创建一个变量即可

class Cell: UITableViewCell {

    var id = ""

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


该代码适用于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 Gist:

感谢您的快速回复,但是“table.indexPathForCell(cell)”仍然会向我返回nil。在我的例子中,“table”是通过IBOutlet连接的,按钮是部分(TableViewCell)的子视图。感谢您的快速回复,但是“tableView.indexPathForRowAtPoint(point)”和“tableView.indexPathForRowAtPoint(point)”仍然返回nil。在我的例子中,“table”是通过IBOutlet连接的,按钮是部分(TableViewCell)的子视图。感谢您的快速回复,我应用了您的解决方案。它对我有用。但我希望有一个合适的替代工作解决方案。不,如果可以添加或删除任何行,则使用基于indexPath的标记将不起作用。@rmaddy。说得好。我更新了我的答案以注意到这一点。由于其他答案对OP不起作用,我在一个新答案中采用了完全不同的方法。由于OP接受了我的原始答案,我不想编辑它,给人留下我的新答案被接受的印象。