it-swarm.com.ru

Нажмите кнопку Get внутри UITableViewCell

У меня есть контроллер представления с представлением таблицы и отдельным пером для шаблона ячейки таблицы. Шаблон ячейки имеет несколько кнопок. Я хочу получить доступ к нажатию кнопки вместе с индексом ячейки, в которой щелкнули внутри контроллера представления, где я определил представление таблицы.

Таким образом, у меня есть ViewController.h и ViewController.m, где у меня есть UITableView и TableTemplate.h, TableTemplate.m и TableTemplate.xib, где у меня определено перо. Я хочу событие нажатия кнопки с индексом ячейки в ViewController.m.

Любая помощь о том, как я могу это сделать?

122
ankit_rck

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

Обновления для нескольких разделов:

Вы можете проверить эту ссылку , чтобы обнаружить нажатие кнопки в табличном представлении для нескольких строк и разделов.

245
Mani

Делегаты путь.

Как видно из других ответов, использование представлений может устареть. Кто знает, что завтра может быть другая оболочка, и, возможно, потребуется использовать cell superview]superview]superview]superview]. И если вы используете теги, вы получите n или более условий для идентификации ячейки. Чтобы избежать всего этого создали делегатов. (Тем самым вы создадите класс ячейки многократного использования. Вы можете использовать тот же класс ячейки, что и базовый класс, и все, что вам нужно сделать, это реализовать методы делегата.)

Сначала нам нужен интерфейс (протокол), который будет использоваться ячейкой для передачи (делегирования) нажатий кнопок. (Вы можете создать отдельный файл .h для протокола и включить его как в контроллер табличного представления, так и в пользовательские классы ячеек OR, просто добавьте его в пользовательский класс ячеек, который в любом случае будет включен в контроллер табличного представления)

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

Включите этот протокол в пользовательский контроллер ячеек и таблиц. И убедитесь, что контроллер табличного представления подтверждает этот протокол. 

В пользовательской ячейке создайте два свойства:

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

В UIButton IBAction делегат щелкает: (То же самое можно сделать для любого действия в пользовательском классе ячеек, которое необходимо делегировать обратно в view controller)

- (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);
}

Это был бы идеальный подход для получения пользовательских действий кнопки ячейки в контроллере табличного представления.

143
GoodSp33d

Вместо того, чтобы играть с тегами, я выбрал другой подход. Сделал делегат для моего подкласса 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)")
}
48
repoguy

Это должно помочь:

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

Здесь отправитель это экземпляр UIButton, который отправляет событие . myTableView - это экземпляр UITableView, с которым вы имеете дело.

Просто получите правильную ссылку на ячейку, и вся работа сделана.

Возможно, вам придется удалить кнопки из содержимого содержимого ячейки & Добавить их непосредственно в экземпляр UITableViewCell в качестве его подпредставления.

Или же 

Вы можете сформулировать схему именования тегов для различных кнопок UIB в cell.contentView . Используя этот тег, позже вы сможете узнать информацию о строках и разделах по мере необходимости.

29
Tarun

Следующий код может помочь вам.

Я взял UITableView с пользовательским классом прототипа ячейки с именем UITableViewCell внутри UIViewController.

Итак, у меня есть ViewController.h, ViewController.m и TableViewCell.h, TableViewCell.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;
}

Пользовательский класс ячейки:

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

Примечание : Здесь я взял все UIControls, используя раскадровку.

Надеюсь, что это может помочь вам ... !!! 

20
Piyush Patel

Причина, по которой мне нравится техника ниже, потому что она также помогает мне определить раздел таблицы.

Кнопка Добавить в ячейке 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
Yogesh Lolusare

Код Таруна не работает на iOS7, так как структура UITableViewCell изменилась, и теперь он получит вместо этого «UITableViewCellScrollView».

Этот пост Получение UITableViewCell с суперпредставлением в 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;
        }
    }

Ссылка содержит код для более многоразового решения, но это должно работать.

6
Stenio Ferreira

Swift 2.2

Вам нужно добавить цель для этой кнопки.

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

FunctionName: подключено // например

И, конечно, вам нужно установить тег этой кнопки, поскольку вы ее используете.

myButton.tag = indexPath.row

Вы можете достичь этого, создав подкласс UITableViewCell. Используйте его в конструкторе интерфейсов, поместите кнопку на эту ячейку, подключите ее через розетку, и все готово.

Чтобы получить тег в подключенной функции:

func connected(sender: UIButton) {
    let buttonTag = sender.tag
    // Do any additional setup
}
6
Himanshu padia

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

В контроллере представления: делегат табличного представления

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

Я считаю, что проще всего создать подкласс для кнопки внутри вашей ячейки (Swift 3):

class MyCellInfoButton: UIButton {
    var indexPath: IndexPath?
}

В вашем классе клетки:

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

В источнике данных табличного представления или представления коллекции при снятии очереди с ячейки присвойте кнопке ее путь индекса:

cell.infoButton.indexPath = indexPath

Таким образом, вы можете просто поместить этот код в свой контроллер табличного представления:

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

И не забудьте установить класс кнопки в Интерфейсном Разработчике и связать его с функцией 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.
    }
}
4
yesleon

Его работа для меня.

 - (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];
}
4
Yogesh Tarsariya
// 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




}
1
Hitesh Chauhan

Используйте 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
    }
}
1
valexa

для Swift 4:

inside the cellForItemAt ,
   
cell.chekbx.addTarget(self, action: #selector(methodname), for: .touchUpInside)

then outside of cellForItemAt
@objc func methodname()
{
//your function code
}

0
Radhe Yadav

Ответ @Mani хорош, однако теги представлений внутри contentView ячейки часто используются для других целей. Вместо этого вы можете использовать тег ячейки (или тег 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
Borzh

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

Внутри "cellForRowAtIndexPath" в MyVC.m:

//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];
}
0
Mer