Ios 如何在不使用sender.tag方法的情况下管理UItableViewCell中的UIbutton?

Ios 如何在不使用sender.tag方法的情况下管理UItableViewCell中的UIbutton?,ios,objective-c,uitableview,uibutton,Ios,Objective C,Uitableview,Uibutton,我有一个里面有按钮的手机。在我的cellForRowAtIndexPath方法中,我以以下方式参照我的uibutton: UIButton *Button= (UIButton *) [cell viewWithTag:3]; 我找到了一个解决方案,类似这样: Button.tag = indexPath.row; [Button addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEve

我有一个里面有按钮的手机。在我的cellForRowAtIndexPath方法中,我以以下方式参照我的uibutton:

UIButton *Button= (UIButton *) [cell viewWithTag:3];
我找到了一个解决方案,类似这样:

Button.tag = indexPath.row;

[Button addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];

-(void)yourButtonClicked:(UIButton*)sender
{
     if (sender.tag == 0) 
     {
         // Your code here
     }
}
但是我的button.tag已经用于从单元格内的其他视图中标识UIbutton视图,我不能将其用于indexpath.row。我该怎么办

编辑


最后,我为UIButton做了一个分类,它似乎是更快的广告可重用解决方案,但这里的每个答案都是有效的选项

您无需使用标签访问按钮,然后为每个单元格设置
选择器。我相信你可以实现更干净的方法

第1步:

在自定义单元格中,将单元格中的
iAction
from按钮拖动到自定义单元格中

@IBAction func buttonTapped(_ sender: Any) {
   //wait for implementation
} 
第二步:

在自定义单元格中,现在声明一个协议

protocol CellsProtocol : NSObjectProtocol {
    func buttonTapped(at index : IndexPath)
}
在同一个类中,也要创建几个变量

weak var delegate : CellsProtocol? = nil
var indexPath : IndexPath! = nil
我们将很快看到这些变量的用法:)

第三步:

让我们回到刚才拖动的
iAction

@IBAction func buttonTapped(_ sender: Any) {
     self.delegate?.buttonTapped(at: self.indexPath)
}
extension ViewController : CellsProtocol {
    func buttonTapped(at index: IndexPath) {
        //here you have indexpath of cell whose button tapped
    }
}
第4步:

现在,您可以回到您的
UITableViewController
并确认您刚才声明的协议

@IBAction func buttonTapped(_ sender: Any) {
     self.delegate?.buttonTapped(at: self.indexPath)
}
extension ViewController : CellsProtocol {
    func buttonTapped(at index: IndexPath) {
        //here you have indexpath of cell whose button tapped
    }
}
第五步:

现在,最后将您的
cellforrowatinexpath更新为

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell : MyTableViewCell = ;
        cell.indexPath = indexPath
        cell.delegate = self
    }
}
就是这样:)现在有一个按钮动作告诉你,单元格点击的按钮:)希望有帮助:)这是一种更通用的方法,因为即使你有多个
ui组件
,你仍然可以使用这种方法

编辑1:

在下面的评论中指出,将indexPath作为属性单元格可能会导致问题,并且单元格不应该关心它的indexPath,应该修改协议以返回单元格,而不是返回索引路径

引用评论:


不一定。您假设正在调用重载数据。你可以 创建一个可见单元格,然后在其上方插入一行。可见细胞 未更新,其indexPath与单元格的 您拥有的indexPath属性未更新。使用单元格本身 作为论据。这比传递索引路径要好得多。如果 代理需要索引路径,代理可以询问表 查看单元格的当前索引路径。一个细胞永远不会在乎 或者知道它的索引路径是什么

上面的陈述很有意义,尤其是一个单元格永远不应该关心或知道它的索引路径是什么。因此,我更新了下面的答案

第1步:

继续并删除单元格中的indexPath属性:)

第二步:

将协议修改为

protocol CellsProtocol : NSObjectProtocol {
    func buttonTapped(in cell : UITableViewCell)
}
第三步:

将IBAction修改为

@IBAction func buttonTapped(_ sender: Any) {
    self.delegate?.buttonTapped(in: self)
}
第4步:

最后,在ViewController中修改协议确认以

extension ViewController : CellsProtocol {

    func buttonTapped(in cell: UITableViewCell) {
        let indexPath = self.tableView.indexPath(for: cell)
        //here you have indexpath of cell whose button tapped
    }
}

就是这样:)

您不需要使用标签访问按钮,然后为每个单元格设置
选择器。我相信你可以实现更干净的方法

第1步:

在自定义单元格中,将单元格中的
iAction
from按钮拖动到自定义单元格中

@IBAction func buttonTapped(_ sender: Any) {
   //wait for implementation
} 
第二步:

在自定义单元格中,现在声明一个协议

protocol CellsProtocol : NSObjectProtocol {
    func buttonTapped(at index : IndexPath)
}
在同一个类中,也要创建几个变量

weak var delegate : CellsProtocol? = nil
var indexPath : IndexPath! = nil
我们将很快看到这些变量的用法:)

第三步:

让我们回到刚才拖动的
iAction

@IBAction func buttonTapped(_ sender: Any) {
     self.delegate?.buttonTapped(at: self.indexPath)
}
extension ViewController : CellsProtocol {
    func buttonTapped(at index: IndexPath) {
        //here you have indexpath of cell whose button tapped
    }
}
第4步:

现在,您可以回到您的
UITableViewController
并确认您刚才声明的协议

@IBAction func buttonTapped(_ sender: Any) {
     self.delegate?.buttonTapped(at: self.indexPath)
}
extension ViewController : CellsProtocol {
    func buttonTapped(at index: IndexPath) {
        //here you have indexpath of cell whose button tapped
    }
}
第五步:

现在,最后将您的
cellforrowatinexpath更新为

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell : MyTableViewCell = ;
        cell.indexPath = indexPath
        cell.delegate = self
    }
}
就是这样:)现在有一个按钮动作告诉你,单元格点击的按钮:)希望有帮助:)这是一种更通用的方法,因为即使你有多个
ui组件
,你仍然可以使用这种方法

编辑1:

在下面的评论中指出,将indexPath作为属性单元格可能会导致问题,并且单元格不应该关心它的indexPath,应该修改协议以返回单元格,而不是返回索引路径

引用评论:


不一定。您假设正在调用重载数据。你可以 创建一个可见单元格,然后在其上方插入一行。可见细胞 未更新,其indexPath与单元格的 您拥有的indexPath属性未更新。使用单元格本身 作为论据。这比传递索引路径要好得多。如果 代理需要索引路径,代理可以询问表 查看单元格的当前索引路径。一个细胞永远不会在乎 或者知道它的索引路径是什么

上面的陈述很有意义,尤其是一个单元格永远不应该关心或知道它的索引路径是什么。因此,我更新了下面的答案

第1步:

继续并删除单元格中的indexPath属性:)

第二步:

将协议修改为

protocol CellsProtocol : NSObjectProtocol {
    func buttonTapped(in cell : UITableViewCell)
}
第三步:

将IBAction修改为

@IBAction func buttonTapped(_ sender: Any) {
    self.delegate?.buttonTapped(in: self)
}
第4步:

最后,在ViewController中修改协议确认以

extension ViewController : CellsProtocol {

    func buttonTapped(in cell: UITableViewCell) {
        let indexPath = self.tableView.indexPath(for: cell)
        //here you have indexpath of cell whose button tapped
    }
}

就是这样:)

创建UIButton的自定义按钮子类,并根据需要定义属性。Button.tag是默认标识符。在自定义类中,可以根据需要提供任意多的属性。然后使用此自定义按钮类而不是UIButton。和用户自定义属性,后跟点(.)和标记。

创建UIButton的自定义按钮子类,并根据需要定义属性。Button.tag是默认标识符。在自定义类中,可以根据需要提供任意多的属性。然后使用此自定义按钮类而不是UIButton。和用户自定义属性,后跟点(.)和标记。

另一个选项-使用“cal”