Две кнопки в UITableViewCell: Как определить, какой indexPath был выбран? - PullRequest
4 голосов
/ 18 января 2011

Я хочу разместить две кнопки в каждой ячейке таблицы.Когда я нажимаю на кнопку номер один, я хочу, чтобы приложение показывало предупреждающее сообщение: «Вы нажали button1 в indexpath: 3,0».Моя проблема: как разместить кнопки в ячейке табличного представления?Кто-нибудь может направить меня?

Ответы [ 2 ]

7 голосов
/ 14 апреля 2012

Взяв ответ @ wedo и немного упростив его - вам, по сути, нужны две части информации: номер строки и столбца, который был нажат («столбец» - это порядок кнопки).


Решение 1 - Неплохое решение

Это можно сохранить на кнопке с помощью button.tag и button.titleLabel.tag. В -tableView:cellForRowAtIndexPath: вы бы сделали это:

UIButton *button0 = [UIButton buttonWithType:UIButtonTypeCustom];
button0.tag = indexPath.row;
button0.titleLabel.tag = 0; // button #0 (or column 0)
[button0 addTarget:self action:@selector(cellButtonAction:)
                        forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button0]; 

Ваш cellButtonAction: метод будет выглядеть так:

- (IBAction)answerButtonAction:(UIButton *)sender {
   NSInteger row = sender.tag;
   NSInteger column = sender.titleLabel.tag;
   // do something
}

Решение 2 - намного лучшее решение

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

@interface IndexPathButton: UIButton

// NSIndexPath provides a convenient way to store an integer pair
// Note we are using cellIndex.section to store the column (or button #)
@property (strong, nonatomic) NSIndexPath *cellIndex;

@end

@implementation IndexPathButton
@end

Вы будете использовать это почти так же, как и в предыдущем решении, но сохраните значения в пользовательском свойстве, а не в тегах. В tableView:cellForRowAtIndexPath:

// You'd create a button for each column here
IndexPathButton *button0 = [IndexPathButton buttonWithType:UIButtonTypeCustom];
button0.indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
[button0 addTarget:self action:@selector(cellButtonAction:)
                        forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button0]; 

Решение 3 - Лучшее решение

UITableViewCells обычно следует использовать делегирование для любых тяжелых работ, которые необходимо выполнить. Этот шаблон наиболее точно соответствует собственному шаблону делегата Apple для ячеек, например tableView:didSelectRowAtIndexPath и друзья. Итак, давайте создадим базовый класс tableViewCell, который можно будет использовать для обработки любого количества элементов управления и который не нужно обмениваться indexPaths.

/** Simple protocol to allow a cell to fire any type of action from a control. */
@protocol SOTableViewCellActionDelegate <NSObject>

@required
-(void)tableViewCell:(UITableViewCell *)cell didFireActionForSender:(id)sender;

@end 

@interface SOActionCell : UITableViewCell

@property (nonatomic, weak) id<SOTableViewCellActionDelegate> delegate;

@end

@implementation SOActionCell

-(void)fireAction:(id)sender
{
   [self.delegate tableViewCell:self didFireActionForSender:sender]; 
}

@end

В -tableView:cellForRowAtIndexPath: вы бы сделали это:

UIButton *button0 = [UIButton buttonWithType:UIButtonTypeCustom];
button0.tag = 0;
[button0 addTarget:cell action:@selector(fireAction:)
                        forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button0]; 

Затем реализуйте необходимый метод делегата в tableViewController:

-(void)tableViewCell:(UITableViewCell *)cell didFireActionForSender:(id)sender
{
   NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
   NSAssert(indexPath, @"indexPath of cell shall always be found."];
   if (!indexPath)
      return;

   // do whatever you want to do with your button action here
   // using indexPath, sender tag, button title, etc.
}
5 голосов
/ 26 августа 2011

Использование indexPath в качестве значения тега в порядке, если в UITableCell есть только одна кнопка, но если вы хотите отслеживать больше, вы можете использовать оператор по модулю:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:              
    (NSIndexPath *)indexPath {
    ...
    imageButton1.tag=indexPath.row*2; 
    [imageButton1 addTarget:self action:@selector(buttonPushed:)
    [cell.contentView addSubview:imageButton];


    ...
    imageButton2.tag=indexPath.row*2+1; 
    [imageButton2 addTarget:self action:@selector(buttonPushed:)
    [cell.contentView addSubview:imageButton];

для селектора вы можете различить кнопки и получить indexPath следующим образом:

-(void) buttonPushed:(id)sender{
 UIButton *button = (UIButton *)sender;

    switch (button.tag%2) {
        case 0:  // imageButton1 is pressed

// to reach indexPath of the cell where the button exists you can use:
//         ((button.tag-button.tag%2)/2)

        break;

        case 1: // imageButton2 is pressed

        break;
    }

Пример для 2 кнопок, но вы можете настроить его в соответствии с количеством кнопок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...