首页 文章

检测在UITableView中按下了哪个UIButton

提问于
浏览
204

我有 UITableView 与5 UITableViewCells . 每个单元格包含 UIButton ,其设置如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [button setTag:1];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell viewWithTag:1];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

我的问题是:在 buttonPressedAction: 方法中,我如何知道按下了哪个按钮 . 我've considered using tags but I'我不确定这是最好的路线 . 我希望能够以某种方式将_1775103标记到控件上 .

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    // how do I know which button sent this message?
    // processing button press for this row requires an indexPath. 
}

这样做的标准方法是什么?

Edit:

我通过以下方式解决了这个问题 . 我仍然想知道这是标准的做法还是有更好的方法?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
     [button setTag:indexPath.row];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    int row = button.tag;
}

需要注意的是,我不能在创建单元格时设置标记,因为单元格可能会出列 . 感觉很脏 . 肯定有更好的办法 .

26 回答

  • 2

    在Apple的Accessory示例中,使用了以下方法:

    [button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    

    然后在触摸处理程序中检索触摸坐标并从该坐标计算索引路径:

    - (void)checkButtonTapped:(id)sender
    {
        CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
        if (indexPath != nil)
        {
         ...
        }
    }
    
  • 0

    我发现使用superview的方法's superview to obtain a reference to the cell'的indexPath工作得很好 . 感谢iphonedevbook.com(macnsmith)提示link text

    -(void)buttonPressed:(id)sender {
     UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
     NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
    ...
    
    }
    
  • 0

    这是我如何做到的 . 简洁明了:

    - (IBAction)buttonTappedAction:(id)sender
    {
        CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                               toView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
        ...
    
  • 0

    在其他地方找到了解决这个问题的好方法,没有弄乱按钮上的标签:

    - (void)buttonPressedAction:(id)sender {
    
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
    
    do stuff with the indexPath...
    }
    
  • 3

    如何使用运行时注入在 UIButton 中发送 NSIndexPath 等信息 .

    1)您需要导入运行时

    2)添加静态常量

    3)使用以下命令在运行时将 NSIndexPath 添加到按钮:

    (void)setMetaData:(id)target withObject:(id)newObj

    4)按下按钮获取元数据使用:

    (id)metaData:(id)target

    请享用

    #import <objc/runtime.h>
        static char const * const kMetaDic = "kMetaDic";
    
    
        #pragma mark - Getters / Setters
    
    - (id)metaData:(id)target {
        return objc_getAssociatedObject(target, kMetaDic);
    }
    
    - (void)setMetaData:(id)target withObject:(id)newObj {
        objc_setAssociatedObject(target, kMetaDic, newObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    
    
        #On the cell constructor
        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
        ....
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        ....
        [btnSocial addTarget:self
                                       action:@selector(openComments:)
                             forControlEvents:UIControlEventTouchUpInside];
    
        #add the indexpath here or another object
        [self setMetaData:btnSocial withObject:indexPath];
    
        ....
        }
    
    
    
        #The action after button been press:
    
        - (IBAction)openComments:(UIButton*)sender{
    
            NSIndexPath *indexPath = [self metaData:sender];
            NSLog(@"indexPath: %d", indexPath.row);
    
            //Reuse your indexpath Now
        }
    
  • 0
    func buttonAction(sender:UIButton!)
        {
            var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tablevw)
           let indexPath = self.tablevw.indexPathForRowAtPoint(position)
           let cell: TableViewCell = tablevw.cellForRowAtIndexPath(indexPath!) as TableViewCell
            println(indexPath?.row)
            println("Button tapped")
        }
    
  • 2

    要做(@Vladimir)的答案是Swift:

    var buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
    var indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!
    

    虽然检查 indexPath != nil 给了我手指...... "NSIndexPath is not a subtype of NSString"

  • 1

    我会像你说的那样使用tag属性,设置标签如下:

    [button setTag:indexPath.row];
    

    然后在buttonPressedAction中获取标签,如下所示:

    ((UIButton *)sender).tag
    

    要么

    UIButton *button = (UIButton *)sender; 
    button.tag;
    
  • 43

    虽然我喜欢标记方式...如果你不想出于任何原因使用标签,你可以创建一个预制按钮的成员 NSArray

    NSArray* buttons ;
    

    然后在渲染tableView之前创建这些按钮并将它们推入数组 .

    然后在 tableView:cellForRowAtIndexPath: 函数内部,您可以执行以下操作:

    UIButton* button = [buttons objectAtIndex:[indexPath row] ] ;
    [cell.contentView addSubview:button];
    

    然后在 buttonPressedAction: 函数中,你可以做到

    - (void)buttonPressedAction:(id)sender {
       UIButton* button = (UIButton*)sender ;
       int row = [buttons indexOfObject:button] ;
       // Do magic
    }
    
  • 48

    处理部分 - 我将NSIndexPath存储在自定义UITableViewCell中

    IN CLKIndexPricesHEADERTableViewCell.xib

    IN IB将UIButton添加到XIB - DONT添加动作!

    添加插座@property(保留,非原子)IBOutlet UIButton * buttonIndexSectionClose;

    请勿在IB中按CTRL拖动操作(在下面的代码中完成)

    @interface CLKIndexPricesHEADERTableViewCell : UITableViewCell
    ...
    @property (retain, nonatomic) IBOutlet UIButton *buttonIndexSectionClose;
    @property (nonatomic, retain) NSIndexPath * indexPathForCell;
    @end
    

    在viewForHeaderInSection中(如果你的表只有1个部分,也应该适用于cellForRow ....等)

    - viewForHeaderInSection is called for each section 1...2...3
    - get the cell CLKIndexPricesHEADERTableViewCell 
    - getTableRowHEADER just does the normal dequeueReusableCellWithIdentifier
    - STORE the indexPath IN the UITableView cell
    - indexPath.section = (NSInteger)section
    - indexPath.row = 0 always (we are only interested in sections)
    
    - (UIView *) tableView:(UITableView *)tableView1 viewForHeaderInSection:(NSInteger)section {
    
    
        //Standard method for getting a UITableViewCell
        CLKIndexPricesHEADERTableViewCell * cellHEADER = [self getTableRowHEADER];
    

    ...使用该部分获取您的单元格的数据

    ...填入

    indexName        = ffaIndex.routeCode;
       indexPrice       = ffaIndex.indexValue;
    
       //
    
       [cellHEADER.buttonIndexSectionClose addTarget:self
                                              action:@selector(buttonDELETEINDEXPressedAction:forEvent:)
                                    forControlEvents:UIControlEventTouchUpInside];
    
    
       cellHEADER.indexPathForCell = [NSIndexPath indexPathForRow:0 inSection:section];
    
    
        return cellHEADER;
    }
    

    USER在Section Headers 上按下DELETE按钮并调用此方法

    - (void)buttonDELETEINDEXPressedAction:(id)sender forEvent:(UIEvent *)event
    {
        NSLog(@"%s", __PRETTY_FUNCTION__);
    
    
        UIView *  parent1 = [sender superview];   // UiTableViewCellContentView
        //UIView *myContentView = (UIView *)parent1;
    
        UIView *  parent2 = [parent1 superview];  // custom cell containing the content view
        //UIView *  parent3 = [parent2 superview];  // UITableView containing the cell
        //UIView *  parent4 = [parent3 superview];  // UIView containing the table
    
    
        if([parent2 isMemberOfClass:[CLKIndexPricesHEADERTableViewCell class]]){
            CLKIndexPricesHEADERTableViewCell *myTableCell = (CLKIndexPricesHEADERTableViewCell *)parent2;
    
            //UITableView *myTable = (UITableView *)parent3;
            //UIView *mainView = (UIView *)parent4;
    
            NSLog(@"%s indexPath.section,row[%d,%d]", __PRETTY_FUNCTION__, myTableCell.indexPathForCell.section,myTableCell.indexPathForCell.row);
    
            NSString *key = [self.sortedKeysArray objectAtIndex:myTableCell.indexPathForCell.section];
            if(key){
                NSLog(@"%s DELETE object at key:%@", __PRETTY_FUNCTION__,key);
                self.keyForSectionIndexToDelete = key;
                self.sectionIndexToDelete = myTableCell.indexPathForCell.section;
    
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Remove Index"
                                                                    message:@"Are you sure"
                                                                   delegate:self
                                                          cancelButtonTitle:@"No"
                                                          otherButtonTitles:@"Yes", nil];
                alertView.tag = kALERTVIEW_REMOVE_ONE_INDEX;
                [alertView show];
                [alertView release];
                //------
            }else{
                NSLog(@"ERROR: [%s] key is nil for section:%d", __PRETTY_FUNCTION__,myTableCell.indexPathForCell.section);
            }
    
        }else{
            NSLog(@"ERROR: [%s] CLKIndexPricesHEADERTableViewCell not found", __PRETTY_FUNCTION__);
        }
    }
    

    在这个例子中,我添加了一个删除按钮,因此应显示UIAlertView以确认它

    我将部分和密钥存储到字典中,存储有关VC中ivar部分的信息

    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
       if(alertView.tag == kALERTVIEW_REMOVE_ONE_INDEX){
            if(buttonIndex==0){
                //NO
                NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
                //do nothing
            }
            else if(buttonIndex==1){
                //YES
                NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
                if(self.keyForSectionIndexToDelete != nil){
    
                    //Remove the section by key
                    [self.indexPricesDictionary removeObjectForKey:self.keyForSectionIndexToDelete];
    
                    //sort the keys so sections appear alphabetically/numbericsearch (minus the one we just removed)
                    [self updateTheSortedKeysArray];                
    
                    //Delete the section from the table using animation
                    [self.tableView beginUpdates];
    
                    [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:self.sectionIndexToDelete]
                                  withRowAnimation:UITableViewRowAnimationAutomatic];
                    [self.tableView endUpdates];
    
                    //required to trigger refresh of myTableCell.indexPathForCell else old values in UITableViewCells
                    [self.tableView reloadData];
                }else{
                    NSLog(@"ERROR: [%s] OBJECT is nil", __PRETTY_FUNCTION__);
                }
            }
            else {
                NSLog(@"ERROR: [%s] UNHANDLED BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
            }
        }else {
            NSLog(@"ERROR: [%s] unhandled ALERTVIEW TAG:%d", __PRETTY_FUNCTION__,alertView.tag);
        }
    }
    
  • 391
    A better way would be to subclass your button and add a indexPath property to it.
    
    //Implement a subclass for UIButton.
    
    @interface NewButton:UIButton
    @property(nonatomic, strong) NSIndexPath *indexPath;
    
    
    Make your button of type NewButton in the XIB or in the code whereever you are initializing them.
    
    Then in the cellForRowAtIndexPath put the following line of code.
    
    button.indexPath = indexPath;
    
    return cell; //As usual
    
    
    
    Now in your IBAction
    
    -(IBAction)buttonClicked:(id)sender{
       NewButton *button = (NewButton *)sender;
    
    //Now access the indexPath by buttons property..
    
       NSIndexPath *indexPath = button.indexPath; //:)
    }
    
  • 0

    这对我有用,谢谢@Cocoanut

    我发现使用superview的superview获取对单元的indexPath的引用的方法非常有效 . 感谢iphonedevbook.com(macnsmith)的提示链接文本

    -(void)buttonPressed:(id)sender {
     UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
     NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
    ...
    
    }
    
  • 1

    使用Swift 4.2和iOS 12,您可以选择以下完整示例中的一个来解决您的问题 .


    #1 . 使用UIView的convert(_:to :)和UITableview的indexPathForRow(at :)

    import UIKit
    
    private class CustomCell: UITableViewCell {
    
        let button = UIButton(type: .system)
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            button.setTitle("Tap", for: .normal)
            contentView.addSubview(button)
    
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
            button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
            button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    }
    
    import UIKit
    
    class TableViewController: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 3
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
            cell.button.addTarget(self, action: #selector(customCellButtonTapped), for: .touchUpInside)
            return cell
        }
    
        @objc func customCellButtonTapped(_ sender: UIButton) {
            let point = sender.convert(CGPoint.zero, to: tableView)
            guard let indexPath = tableView.indexPathForRow(at: point) else { return }
            print(indexPath)
        }
    
    }
    

    #2 . 使用UIView的convert(_:to :)和UITableview的indexPathForRow(at :)(替代)

    这是前一个示例的替代方法,我们将 nil 传递给 addTarget(_:action:for:) 中的 target 参数 . 这样,如果第一响应者没有实现该动作,它将被发送到响应者链中的下一个响应者,直到找到正确的实现 .

    import UIKit
    
    private class CustomCell: UITableViewCell {
    
        let button = UIButton(type: .system)
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            button.setTitle("Tap", for: .normal)
            button.addTarget(nil, action: #selector(TableViewController.customCellButtonTapped), for: .touchUpInside)
            contentView.addSubview(button)
    
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
            button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
            button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    }
    
    import UIKit
    
    class TableViewController: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 3
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
            return cell
        }
    
        @objc func customCellButtonTapped(_ sender: UIButton) {
            let point = sender.convert(CGPoint.zero, to: tableView)
            guard let indexPath = tableView.indexPathForRow(at: point) else { return }
            print(indexPath)
        }
    
    }
    

    #3 . 使用UITableview的indexPath(用于:)和委托模式

    在此示例中,我们将视图控制器设置为单元的委托 . 当点击单元格的按钮时,它会触发对委托的适当方法的调用 .

    import UIKit
    
    protocol CustomCellDelegate: AnyObject {
        func customCellButtonTapped(_ customCell: CustomCell)
    }
    
    class CustomCell: UITableViewCell {
    
        let button = UIButton(type: .system)
        weak var delegate: CustomCellDelegate?
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            button.setTitle("Tap", for: .normal)
            button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
            contentView.addSubview(button)
    
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
            button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
            button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        @objc func buttonTapped(sender: UIButton) {
            delegate?.customCellButtonTapped(self)
        }
    
    }
    
    import UIKit
    
    class TableViewController: UITableViewController, CustomCellDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 3
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
            cell.delegate = self
            return cell
        }
    
        // MARK: - CustomCellDelegate
    
        func customCellButtonTapped(_ customCell: CustomCell) {
            guard let indexPath = tableView.indexPath(for: customCell) else { return }
            print(indexPath)
        }
    
    }
    

    #4 . 使用UITableview的indexPath(for :)和一个用于委托的闭包

    这是前一个示例的替代方法,我们使用闭包而不是协议委托声明处理按钮水龙头 .

    import UIKit
    
    class CustomCell: UITableViewCell {
    
        let button = UIButton(type: .system)
        var buttontappedClosure: ((CustomCell) -> Void)?
    
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            button.setTitle("Tap", for: .normal)
            button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
            contentView.addSubview(button)
    
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
            button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
            button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        @objc func buttonTapped(sender: UIButton) {
            buttontappedClosure?(self)
        }
    
    }
    
    import UIKit
    
    class TableViewController: UITableViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 3
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
            cell.buttontappedClosure = { [weak tableView] cell in
                guard let indexPath = tableView?.indexPath(for: cell) else { return }
                print(indexPath)
            }
            return cell
        }
    
    }
    
  • 0

    你可以使用标签模式:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         NSString *identifier = @"identifier";
         UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
         if (cell == nil) {
             cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
             [cell autorelelase];
    
             UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
             [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
             [button setTag:[indexPath row]]; //use the row as the current tag
             [cell.contentView addSubview:button];
    
             [button release];
         }
    
         UIButton *button = (UIButton *)[cell viewWithTag:[indexPath row]]; //use [indexPath row]
         [button setTitle:@"Edit" forState:UIControlStateNormal];
    
         return cell;
    }
    
    - (void)buttonPressedAction:(id)sender
    {
        UIButton *button = (UIButton *)sender;
        //button.tag has the row number (you can convert it to indexPath)
    }
    
  • 5

    我错过了什么吗?你不能只使用发件人来识别按钮 . 发件人会给你这样的信息:

    <UIButton: 0x4b95c10; frame = (246 26; 30 30); opaque = NO; tag = 104; layer = <CALayer: 0x4b95be0>>
    

    然后,如果您想要更改按钮的属性,请说明您告诉发件人的背景图片:

    [sender setBackgroundImage:[UIImage imageNamed:@"new-image.png"] forState:UIControlStateNormal];
    

    如果你需要标签,那么ACBurk的方法就可以了 .

  • 0
    // how do I know which button sent this message?
    // processing button press for this row requires an indexPath.
    

    实际上很简单:

    - (void)buttonPressedAction:(id)sender
    {
        UIButton *button = (UIButton *)sender;
        CGPoint rowButtonCenterInTableView = [[rowButton superview] convertPoint:rowButton.center toView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rowButtonCenterInTableView];
        MyTableViewItem *rowItem = [self.itemsArray objectAtIndex:indexPath.row];
        // Now you're good to go.. do what the intention of the button is, but with
        // the context of the "row item" that the button belongs to
        [self performFooWithItem:rowItem];
    }
    

    对我有用:P

    如果要调整目标操作设置,可以在方法中包含事件参数,然后使用该事件的触摸来解析触摸的坐标 . 仍然需要在触摸视图边界中解析坐标,但对于某些人来说这似乎更容易 .

  • 0

    创建一个nsmutable数组并将所有按钮放在该数组usint中[array addObject:yourButton];

    在按钮按下方法

    (void)buttonPressedAction:(id)sender
    {
        UIButton *button = (UIButton *)sender;
    
    for(int i=0;i<[yourArray count];i++){
    
    if([buton isEqual:[yourArray objectAtIndex:i]]){
    
    //here write wat u need to do
    
    }
    }
    
  • 5

    当按钮位于表格的页脚(这会阻止您找到“点击的单元格”时),Cocoanuts答案(这有助于我解决这个问题)略有不同:

    -(IBAction) buttonAction:(id)sender;
    {
        id parent1 = [sender superview];   // UiTableViewCellContentView
        id parent2 = [parent1 superview];  // custom cell containing the content view
        id parent3 = [parent2 superview];  // UITableView containing the cell
        id parent4 = [parent3 superview];  // UIView containing the table
    
        UIView *myContentView = (UIView *)parent1;
        UITableViewCell *myTableCell = (UITableViewCell *)parent2;
        UITableView *myTable = (UITableView *)parent3;
        UIView *mainView = (UIView *)parent4;
    
        CGRect footerViewRect = myTableCell.frame;
        CGRect rect3 = [myTable convertRect:footerViewRect toView:mainView];    
    
        [cc doSomethingOnScreenAtY:rect3.origin.y];
    }
    
  • 0

    我总是使用标签 .

    你需要子类化 UITableviewCell 并从那里按下按钮 .

  • 6

    这很简单;制作一个自定义单元格并按下按钮

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
             NSString *identifier = @"identifier";
            customCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    
        cell.yourButton.tag = indexPath.Row;
    
    - (void)buttonPressedAction:(id)sender
    

    将上述方法中的id更改为 (UIButton *)

    您可以通过执行sender.tag来获取正在点击哪个按钮的值 .

  • 0

    子类按钮来存储所需的值,也许创建一个协议(ControlWithData或其他东西) . 将按钮添加到表格视图单元格时设置值 . 在您的补足事件中,查看发件人是否遵守协议并提取数据 . 我通常存储对表视图单元格上呈现的实际对象的引用 .

  • 0

    SWIFT 2 UPDATE

    在这里's how to find out which button was tapped + send data to another ViewController from that button' s indexPath.row 因为我最重要的一点!

    @IBAction func yourButton(sender: AnyObject) {
    
    
         var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
            let indexPath = self.tableView.indexPathForRowAtPoint(position)
            let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
            UITableViewCell
            print(indexPath?.row)
            print("Tap tap tap tap")
    
        }
    

    对于那些使用ViewController类并添加了tableView的人,我使用的是ViewController而不是TableViewController,因此我手动添加了tableView以便访问它 .

    这是在点击该按钮并传递单元格的时候将数据传递给另一个VC的代码 indexPath.row

    @IBAction func moreInfo(sender: AnyObject) {
    
        let yourOtherVC = self.storyboard!.instantiateViewControllerWithIdentifier("yourOtherVC") as! YourOtherVCVIewController
    
    
    
        var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
        let indexPath = self.tableView.indexPathForRowAtPoint(position)
        let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
        UITableViewCell
        print(indexPath?.row)
        print("Button tapped")
    
    
        yourOtherVC.yourVarName = [self.otherVCVariable[indexPath!.row]]
    
        self.presentViewController(yourNewVC, animated: true, completion: nil)
    
    }
    
  • 5

    请注意,我在使用自定义单元格,此代码非常适合我

    @IBAction func call(sender: UIButton)
        {
            var contentView = sender.superview;
            var cell = contentView?.superview as EmployeeListCustomCell
            if (!(cell.isKindOfClass(EmployeeListCustomCell)))
            {
                cell = (contentView?.superview)?.superview as EmployeeListCustomCell
            }
    
            let phone = cell.lblDescriptionText.text!
            //let phone = detailObject!.mobile!
            let url:NSURL = NSURL(string:"tel://"+phone)!;
            UIApplication.sharedApplication().openURL(url);
        }
    
  • 3

    Chris Schwerdt的解决方案然后在Swift为我工作:

    @IBAction func rateButtonTapped(sender: UIButton) {
        let buttonPosition : CGPoint = sender.convertPoint(CGPointZero, toView: self.ratingTableView)
        let indexPath : NSIndexPath = self.ratingTableView.indexPathForRowAtPoint(buttonPosition)!
    
        print(sender.tag)
        print(indexPath.row)
    }
    
  • 0

    这个问题有两个部分:

    1) Getting the index path of UITableViewCell which contains pressed UIButton

    有一些建议,如:

    • 使用索引路径的 row 值在 cellForRowAtIndexPath: 方法中更新 UIButtontag . 这不是一个好的解决方案,因为它需要连续更新 tag ,它不适用于具有多个部分的表视图 .

    • NSIndexPath 属性添加到自定义单元格并在 cellForRowAtIndexPath: 方法中更新它而不是 UIButtontag . 这解决了多节问题,但仍然不好,因为它总是需要更新 .

    • 在创建自定义单元格时使用自定义单元格中的父级 UITableView ,并使用 indexPathForCell: 方法获取索引路径 . 看起来好一点,不需要在 cellForRowAtIndexPath: 方法中更新任何内容,但仍需要在创建自定义单元格时设置弱引用 .

    • 使用单元格的 superView 属性获取对父 UITableView 的引用 . 无需向自定义单元格添加任何属性,也无需在创建/稍后设置/更新任何内容 . 但是单元格 superView 取决于iOS实现细节 . 所以它不能直接使用 .

    但这可以使用一个简单的循环来实现,因为我们确定所讨论的单元格必须位于UITableView中:

    UIView* view = self;
    while (view && ![view isKindOfClass:UITableView.class])
        view = view.superview;
    UITableView* parentTableView = (UITableView*)view;
    

    因此,这些建议可以组合成一个简单而安全的自定义单元格方法来获取索引路径:

    - (NSIndexPath *)indexPath
    {
        UIView* view = self;
    
        while (view && ![view isKindOfClass:UITableView.class])
            view = view.superview;
    
        return [(UITableView*)view indexPathForCell:self];
    }
    

    从现在开始,此方法可用于检测按下哪个 UIButton .

    2) Informing other parties about button press event

    在内部知道哪个 UIButton 被按下了具有精确索引路径的自定义单元格之后,需要将此信息发送给其他方(很可能是处理 UITableView 的视图控制器) . 因此,这个按钮单击事件可以在类似的抽象和逻辑级别处理到UITableView委托的 didSelectRowAtIndexPath: 方法 .

    可以使用两种方法:

    a) Delegation: 自定义单元格可以具有 delegate 属性,并可以定义协议 . 按下按钮时,它只执行's delegate methods on it' s delegate 属性 . 但是,创建它们时,需要为每个自定义单元格设置此 delegate 属性 . 作为备选,自定义单元格也可以选择在其上执行其委托方法's parent table view' s delegate .

    b) Notification Center: 自定义单元格可以定义自定义通知名称,并使用 userInfo 对象中提供的索引路径和父表视图信息发布此通知 . 无需为每个单元格设置任何内容,只需为自定义单元格的通知添加观察者即可 .

  • 0

    我使用了一个子类 UIButton 的解决方案,我想我应该在这里分享它,Swift中的代码:

    class ButtonWithIndexPath : UIButton {
        var indexPath:IndexPath?
    }
    

    然后记得在 cellForRow(at:) 更新它的indexPath

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        let returnCell = tableView.dequeueReusableCell(withIdentifier: "cellWithButton", for: indexPath) as! cellWithButton
        ...
        returnCell.button.indexPath = IndexPath
        returnCell.button.addTarget(self, action:#selector(cellButtonPressed(_:)), for: .touchUpInside)
    
        return returnCell
    }
    

    因此,当响应按钮的事件时,您可以像使用它一样使用它

    func cellButtonPressed(_ sender:UIButton) {
        if sender is ButtonWithIndexPath {
            let button = sender as! ButtonWithIndexPath
            print(button.indexPath)
        }
    }
    

相关问题