首页 文章

在UITableViewCell中单击获取按钮

提问于
浏览
117

我有一个视图控制器,具有表视图和表单元格模板的单独的笔尖 . 单元格模板有一些按钮 . 我想访问按钮单击以及在我已定义表视图的视图控制器内单击的单元格的索引 .

所以我有 ViewController.hViewController.m ,我有 UITableViewTableTemplate.hTableTemplate.mTableTemplate.xib ,我有定义的笔尖 . 我想在 ViewController.m 中使用单元格索引的按钮单击事件 .

有什么帮助,我该怎么办?

17 回答

  • 242

    1)在 cellForRowAtIndexPath: 方法中,将按钮标记指定为索引:

    cell.yourbutton.tag = indexPath.row;
    

    2)为按钮添加目标和操作,如下所示:

    [cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    

    3)基于索引的代码动作如下 ViewControler

    -(void)yourButtonClicked:(UIButton*)sender
    {
         if (sender.tag == 0) 
         {
             // Your code here
         }
    }
    

    Updates for multiple Section:

    您可以检查this link以检测表格视图中的按钮单击多行和部分 .

  • 6

    Delegates are the way to go.

    正如其他使用视图的答案所见,可能会过时 . 谁知道明天可能会有另一个包装器,可能需要使用 cell superview]superview]superview]superview] . 如果使用标签,最终会有n个if else条件来识别单元格 . 为了避免所有这些设置委托 . (通过这样做,您将创建一个可用的单元类 . 您可以使用相同的单元类作为基类,您所要做的就是实现委托方法 . )

    首先,我们需要一个接口(协议),单元将用于通信(委托)按钮点击 . (您可以为协议创建单独的.h文件,并包含在表视图控制器和自定义单元类中,或者只将其添加到自定义单元类中,无论如何都将其包含在表视图控制器中)

    @protocol CellDelegate <NSObject>
    - (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
    @end
    

    在自定义单元格和表格视图控制器中包含此协议 . 并确保表视图控制器确认此协议 .

    在自定义单元格中创建两个属性

    @property (weak, nonatomic) id<CellDelegate>delegate;
    @property (assign, nonatomic) NSInteger cellIndex;
    

    UIButton IBAction委托中单击:(可以对自定义单元类中需要委托回视图控制器的任何操作执行相同操作)

    - (IBAction)buttonClicked:(UIButton *)sender {
        if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
            [self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
        }
    }
    

    在取消单元格后的表视图控制器 cellForRowAtIndexPath 中,设置上述属性 .

    cell.delegate = self;
    cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.
    

    并在表视图控制器中实现委托:

    - (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
    {
        // Do additional actions as required.
        NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
    }
    

    这将是在表视图控制器中获取自定义单元格按钮操作的理想方法 .

  • 0

    我采取了不同的方法,而不是玩标签 . 为我的UITableViewCell子类(OptionButtonsCell)制作了委托,并添加了一个indexPath var . 从我在故事板中的按钮,我将@IBAction连接到OptionButtonsCell,然后我向任何感兴趣的人发送带有正确indexPath的委托方法 . 在索引路径的单元格中我设置当前indexPath并且它工作:)

    让代码说明一切:

    Swift 3 Xcode 8

    OptionButtonsTableViewCell.swift

    import UIKit
    protocol OptionButtonsDelegate{
        func closeFriendsTapped(at index:IndexPath)
    }
    class OptionButtonsTableViewCell: UITableViewCell {
        var delegate:OptionButtonsDelegate!
        @IBOutlet weak var closeFriendsBtn: UIButton!
        var indexPath:IndexPath!
        @IBAction func closeFriendsAction(_ sender: UIButton) {
            self.delegate?.closeFriendsTapped(at: indexPath)
        }
    }
    

    MyTableViewController.swift

    class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {...
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell
        cell.delegate = self
        cell.indexPath = indexPath
        return cell   
    }
    
    func closeFriendsTapped(at index: IndexPath) {
         print("button tapped at index:\(index)")
    }
    
  • 44

    这应该有所帮助: -

    UITableViewCell* cell = (UITableViewCell*)[sender superview];
    NSIndexPath* indexPath = [myTableView indexPathForCell:cell];
    

    这里 sender 是发送事件的UIButton实例 . myTableView 是您正在处理的UITableView实例 .

    只需获得正确的单元格参考,所有工作都已完成 .

    您可能需要从单元格的contentView中删除按钮,并将它们直接添加到UITableViewCell实例,因为它是子视图 .

    要么

    您可以在cell.contentView中为不同的UIButton制定标记命名方案 . 使用此标记,稍后您可以根据需要了解行和部分信息 .

  • 0

    以下代码可能会帮助您 .

    我在 UIViewController 中使用了名为 UITableViewCell 的自定义原型单元类 UITableView .

    所以我有 ViewController.hViewController.mTableViewCell.hTableViewCell.m

    这是代码:

    ViewController.h

    @interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
    
    @property (strong, nonatomic) IBOutlet UITableView *tblView;
    
    @end
    

    ViewController.m

    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return (YourNumberOfRows);
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        static NSString *cellIdentifier = @"cell";
    
        __weak TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    
        if (indexPath.row==0) {
            [cell setDidTapButtonBlock:^(id sender)
             {
                 // Your code here
    
             }];
        }    
        return cell;
    }
    

    Custom cell class :

    TableViewCell.h
    
    @interface TableViewCell : UITableViewCell
    
    @property (copy, nonatomic) void (^didTapButtonBlock)(id sender);
    
    @property (strong, nonatomic) IBOutlet UILabel *lblTitle;
    @property (strong, nonatomic) IBOutlet UIButton *btnAction;
    
    - (void)setDidTapButtonBlock:(void (^)(id sender))didTapButtonBlock;
    
    @end
    

    UITableViewCell.m
    
    @implementation TableViewCell
    
    - (void)awakeFromNib {
        // Initialization code
        [self.btnAction addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];
    
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    - (void)didTapButton:(id)sender {
        if (self.didTapButtonBlock)
        {
            self.didTapButtonBlock(sender);
        }
    }
    

    Note :我在这里使用了Storyboard全部 UIControls .

    希望能帮到你...... !!!

  • 6

    我喜欢下面的技术,因为它也帮助我识别表的部分 .

    在单元格cellForRowAtIndexPath中添加按钮:

    UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
            [selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)];
            [selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun 
        [selectTaskBtn addTarget:self action:@selector(addTask:)   forControlEvents:UIControlEventTouchDown];
    [cell addsubview: selectTaskBtn];
    

    事件addTask:

    -(void)addTask:(UIButton*)btn
    {
        CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
        if (indexPath != nil)
        {
         int currentIndex = indexPath.row;
         int tableSection = indexPath.section;
        }
    }
    

    希望这有帮助 .

  • 12

    Tarun的代码在iOS7上不起作用,因为UITableViewCell结构已经改变,现在他将获得“UITableViewCellScrollView” .

    这篇文章Getting UITableViewCell with superview in iOS 7有一个很好的解决方案,可以创建一个循环来查找正确的父视图,而不管结构中是否有任何未来的变化 . 归结为创建一个循环:

    UIView *superView = [sender superview];
        UIView *foundSuperView = nil;
    
        while (nil != superView && nil == foundSuperView) {
            if ([superView isKindOfClass:[UITableViewCell class]]) {
                foundSuperView = superView;
            } else {
                superView = superView.superview;
            }
        }
    

    该链接具有更可重用的解决方案的代码,但这应该有效 .

  • 29

    Swift 2.2

    您需要为该按钮添加目标 .

    myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)
    

    FunctionName: connected //例如

    当然,您需要设置该按钮的标签,因为您正在使用它 .

    myButton.tag = indexPath.row
    

    您可以通过继承UITableViewCell来实现此目的 . 在界面构建器中使用它,在该单元格上放置一个按钮,通过插座连接它,然后你去 .

    要在连接函数中获取标记:

    func connected(sender: UIButton) {
        let buttonTag = sender.tag
        // Do any additional setup
    }
    
  • 0

    Swift 3 with a Closure

    一个不错的解决方案是在自定义UITableViewCell中使用闭包来回调viewController以获取操作 .

    在细胞中:

    final class YourCustomCell: UITableViewCell {
    
        var callbackClosure: (() -> Void)?
    
        // Configure the cell here
        func configure(object: Object, callbackClosure: (() -> Void)?) {
           self.callbackClosure = callbackClosure
        }
    
    
    // MARK: - IBAction
    extension YourCustomCell {
        @IBAction fileprivate func actionPressed(_ sender: Any) {
            guard let closure = callbackClosure else { return }
            closure()
        }
    }
    

    在View Controller中:Tableview委托

    extension YourViewController: UITableViewDelegate {
    
        func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            guard let cell: YourCustomCell = cell as? YourCustomCell else { return }
            cell.configure(object: object, callbackClosure: { [weak self] in
                self?.buttonAction()
            })
         }
     }
    
    fileprivate extension YourViewController {
    
        func buttonAction() {
            // do your actions here 
        }
    }
    
  • 140

    我发现将单元格中的按钮子类化是最简单的(Swift 3):

    class MyCellInfoButton: UIButton {
        var indexPath: IndexPath?
    }
    

    在你的细胞类中:

    class MyCell: UICollectionViewCell {
        @IBOutlet weak var infoButton: MyCellInfoButton!
       ...
    }
    

    在表视图或集合视图的数据中source,当出列单元格时,给按钮指定索引:

    cell.infoButton.indexPath = indexPath
    

    所以你可以把这些代码放到你的表视图控制器中:

    @IBAction func handleTapOnCellInfoButton(_ sender: MyCellInfoButton) {
            print(sender.indexPath!) // Do whatever you want with the index path!
    }
    

    在接口生成器中输入't forget to set the button'类,并将其链接到 handleTapOnCellInfoButton 函数!


    编辑:

    使用依赖注入 . 要设置调用闭包:

    class MyCell: UICollectionViewCell {
        var someFunction: (() -> Void)?
        ...
        @IBAction func didTapInfoButton() {
            someFunction?()
        }
    }
    

    并在集合视图的委托的willDisplay方法中注入闭包:

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        (cell as? MyCell)?.someFunction = {
            print(indexPath) // Do something with the indexPath.
        }
    }
    
  • -1

    它的工作对我来说 .

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
         UIButton *Btn_Play = (UIButton *)[cell viewWithTag:101];
         [Btn_Play addTarget:self action:@selector(ButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    }
    -(void)ButtonClicked:(UIButton*)sender {
         CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.Tbl_Name];
         NSIndexPath *indexPath = [self.Tbl_Name indexPathForRowAtPoint:buttonPosition];
    }
    
  • 20
    // Add action in cell for row at index path -tableView
    
    cell.buttonName.addTarget(self, action: #selector(ViewController.btnAction(_:)), for: .touchUpInside)
    
    // Button Action
    
      @objc func btnAction(_ sender: AnyObject) {
    
    
    
            var position: CGPoint = sender.convert(.zero, to: self.tableView)
    
    
            let indexPath = self.tableView.indexPathForRow(at: position)
            let cell: UITableViewCell = tableView.cellForRow(at: indexPath!)! as
            UITableViewCell
    
    
    
    
    }
    
  • 5

    @Mani答案很好,但是单元格内容视图中的视图标记通常用于其他目的 . 您可以使用单元格的标记(或单元格的contentView标记):

    1)在 cellForRowAtIndexPath: 方法中,将单元格的标记指定为索引:

    cell.tag = indexPath.row; // or cell.contentView.tag...
    

    2)为按钮添加目标和操作,如下所示:

    [cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    

    3)创建返回发送方行的方法(感谢@Stenio Ferreira):

    - (NSInteger)rowOfSender:(id)sender
    {
        UIView *superView = sender.superview;
        while (superView) {
            if ([superView isKindOfClass:[UITableViewCell class]])
                break;
            else
                superView = superView.superview;
        }
    
        return superView.tag;
    }
    

    4)基于索引的代码操作:

    -(void)yourButtonClicked:(UIButton*)sender
    {
         NSInteger index = [self rowOfSender:sender];
         // Your code here
    }
    
  • 0

    CustomTableCell.h是一个UITableViewCell:

    @property (weak, nonatomic) IBOutlet UIButton *action1Button;
    @property (weak, nonatomic) IBOutlet UIButton *action2Button;
    

    进口后的MyVC.m:

    @interface MYTapGestureRecognizer : UITapGestureRecognizer
    @property (nonatomic) NSInteger dataint;
    @end
    

    在MyVC.m中的“cellForRowAtIndexPath”内:

    //CustomTableCell 
    CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    
    //Set title buttons
    [cell.action1Button setTitle:[NSString stringWithString:NSLocalizedString(@"action1", nil)] forState:UIControlStateNormal];
    [cell.action2Button setTitle:[NSString stringWithString:NSLocalizedString(@"action2", nil)] forState:UIControlStateNormal];
    
    //Set visibility buttons
    [cell.action1Button setHidden:FALSE];
    [cell.action2Button setHidden:FALSE];
    
    //Do 1 action
    [cell.action1Button addTarget:self action:@selector(do1Action :) forControlEvents:UIControlEventTouchUpInside];
    
    //Do 2 action
    MYTapGestureRecognizer *action2Tap = [[MYTapGestureRecognizer alloc] initWithTarget:self action:@selector(do2Action :)];
    cancelTap.numberOfTapsRequired = 1;
    cancelTap.dataint = indexPath.row;
    [cell.action2Button setUserInteractionEnabled:YES];
    [cell.action2Button addGestureRecognizer:action2Tap];
    

    MyVC.m:

    -(void)do1Action :(id)sender{
    //do some action that is not necessary fr data
    }
    
    -(void)do2Action :(UITapGestureRecognizer *)tapRecognizer{
    MYTapGestureRecognizer *tap = (MYTapGestureRecognizer *)tapRecognizer;
    numberTag = tap.dataint;
    FriendRequest *fr = [_list objectAtIndex:numberTag];
    
    //connect with a WS o do some action with fr data
    
    //actualize list in tableView
     [self.myTableView reloadData];
    }
    
  • 1

    使用Swift闭包:

    class TheCell: UITableViewCell {
    
        var tapCallback: (() -> Void)?
    
        @IBAction func didTap(_ sender: Any) {
            tapCallback?()
        }
    }
    
    extension TheController: UITableViewDataSource {
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                let cell = tableView.dequeueReusableCell(withIdentifier: TheCell.identifier, for: indexPath) as! TheCell {
                cell.tapCallback = {
                    //do stuff
                }
                return cell
        }
    }
    
  • 4

    对于swift 4:

    inside the cellForItemAt ,
       
    cell.chekbx.addTarget(self, action: #selector(methodname), for: .touchUpInside)
    
    then outside of cellForItemAt
    @objc func methodname()
    {
    //your function code
    }
    
  • 4
    cell.show.tag=indexPath.row;
         [cell.show addTarget:self action:@selector(showdata:) forControlEvents:UIControlEventTouchUpInside];
    
    -(IBAction)showdata:(id)sender
    {
        UIButton *button = (UIButton *)sender;
    
        UIStoryboard *storyBoard;
        storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        SecondViewController *detailView = [storyBoard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    
        detailView.string=[NSString stringWithFormat:@"%@",[_array objectAtIndex:button.tag]];
    
        [self presentViewController:detailView animated:YES completion:nil];
    
    }
    

相关问题