在UITableViewCell中单击获取按钮

ank*_*rck 134 objective-c uibutton uitableview ios

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

所以,我有ViewController.hViewController.m在那里我有UITableViewTableTemplate.h,TableTemplate.mTableTemplate.xib在那里我有定义的笔尖.我想要单元格索引的按钮单击事件ViewController.m.

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

Man*_*ani 253

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

cell.yourbutton.tag = indexPath.row;
Run Code Online (Sandbox Code Playgroud)

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

[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
Run Code Online (Sandbox Code Playgroud)

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

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

多个部分的更新:

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

  • 当您开始插入和删除行时,此解决方案会遇到问题.移动行时不会更新标记.而不是保持对行的引用.保持对唯一对象id的引用可能更好. (21认同)

Goo*_*33d 145

代表是要走的路.

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

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

@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end
Run Code Online (Sandbox Code Playgroud)

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

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

@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;
Run Code Online (Sandbox Code Playgroud)

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

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

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

cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 为什么你让委托成为单元格的强大属性?这将为您提供一个保留周期,除非您知道控制器只是微弱地保留了单元格。 (3认同)
  • 我从我的一位朋友那里听说,在每个单元格上使用委托导致内存消耗,所以使用标签.这是真的? (2认同)
  • 检查此问题花花公子http://stackoverflow.com/questions/31649220/detect-button-click-in-table-view-ios-xcode-for-multiple-row-and-section (2认同)

rep*_*guy 60

我采取了不同的方法,而不是玩标签.为我的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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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)")
}
Run Code Online (Sandbox Code Playgroud)

  • 最好和最干净的解决方案! (2认同)

Tar*_*run 30

这应该有所帮助: -

UITableViewCell* cell = (UITableViewCell*)[sender superview];
NSIndexPath* indexPath = [myTableView indexPathForCell:cell];
Run Code Online (Sandbox Code Playgroud)

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

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

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

要么

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

  • 它应该是[[发送者superview] superview]; (4认同)
  • 现在在iOS 7中它应该是UITableViewCell*cell =(UITableViewCell*)[[[sender superview] superview] superview]; 谢谢. (3认同)
  • 这对于非常简单的细胞是有益的.但是,如果你的细胞有一个深层的视图,Mani的答案是最好的. (2认同)

Piy*_*ush 21

以下代码可能会帮助您.

我已经采用UITableView了名为UITableViewCellinside的自定义原型单元类UIViewController.

所以我有ViewController.h,ViewController.m并且TableViewCell.h,TableViewCell.m

这是代码:

ViewController.h

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tblView;

@end
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

自定义单元类:

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
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这里我UIControls使用了Storyboard.

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


Yog*_*are 14

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

在单元格cellForRowAtIndexPath中添加Button:

 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];
Run Code Online (Sandbox Code Playgroud)

事件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;
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这有帮助.


Ste*_*ira 6

Tarun的代码在iOS7上不起作用,因为UITableViewCell结构发生了变化,现在他将获得"UITableViewCellScrollView".

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

    UIView *superView = [sender superview];
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView) {
        if ([superView isKindOfClass:[UITableViewCell class]]) {
            foundSuperView = superView;
        } else {
            superView = superView.superview;
        }
    }
Run Code Online (Sandbox Code Playgroud)

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


Him*_*dia 6

Swift 2.2

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

myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)
Run Code Online (Sandbox Code Playgroud)

FunctionName:连接 //例如

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

myButton.tag = indexPath.row
Run Code Online (Sandbox Code Playgroud)

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

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

func connected(sender: UIButton) {
    let buttonTag = sender.tag
    // Do any additional setup
}
Run Code Online (Sandbox Code Playgroud)


val*_*exa 6

使用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
    }
}
Run Code Online (Sandbox Code Playgroud)


yes*_*eon 5

我发现最简单的方法是将单元格内的按钮归类(Swift 3):

class MyCellInfoButton: UIButton {
    var indexPath: IndexPath?
}
Run Code Online (Sandbox Code Playgroud)

在您的单元格班级中:

class MyCell: UICollectionViewCell {
    @IBOutlet weak var infoButton: MyCellInfoButton!
   ...
}
Run Code Online (Sandbox Code Playgroud)

在表视图或集合视图的数据源中,使单元出队时,为按钮提供其索引路径:

cell.infoButton.indexPath = indexPath
Run Code Online (Sandbox Code Playgroud)

因此,您可以将这些代码放入表视图控制器中:

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

并且不要忘记在Interface Builder中设置按钮的类并将其链接到handleTapOnCellInfoButton函数!


编辑:

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

class MyCell: UICollectionViewCell {
    var someFunction: (() -> Void)?
    ...
    @IBAction func didTapInfoButton() {
        someFunction?()
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    (cell as? MyCell)?.someFunction = {
        print(indexPath) // Do something with the indexPath.
    }
}
Run Code Online (Sandbox Code Playgroud)


Sev*_*y11 5

Swift 3带有关闭

一个很好的解决方案是在自定义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()
    }
}
Run Code Online (Sandbox Code Playgroud)

在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 
    }
}
Run Code Online (Sandbox Code Playgroud)


Yog*_*iya 5

它为我工作。

 - (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];
}
Run Code Online (Sandbox Code Playgroud)