Рецепты для передачи данных из UITableViewCell в UITableViewController - PullRequest
3 голосов
/ 25 января 2012

Я выясняю правильный механизм для передачи данных из UITableViewCell s в UIableViewController (или UIViewController).

Поиск в стековом потоке Я нашел разные способы сделать это и, наконец, янашел механизм, который работает хорошо, но я не знаю, может ли это быть правильный подход.

Это сценарий.Сначала я создал пользовательскую ячейку (связанную с интерфейсом xib) с именем DataTableViewCell, которая расширяет UITableViewCell.В этой ячейке есть выход для отображения (и изменения) данных и дополнительное свойство, называемое index, например:

@property (nonatomic, copy) NSIndexPath* index;

Это свойство обновляется внутри метода cellForRowAtIndexPath в методе UITableViewController:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    DataTableViewCell *cell = (DataTableViewCell*)[tv dequeueReusableCellWithIdentifier:kCellTableIdentifier];
    if (cell == nil)
    {
        [[NSBundle mainBundle] loadNibNamed:@"DataTableViewCell" owner:self options:nil];     
        cell = (DataTableViewCell*)self.dataTableViewCellOutlet;
    }

    // configure the cell with data
    // do stuff here...

    // configure the cell with the current indexPath
    cell.index = indexPath;    

    return cell;
}

Поскольку в ячейке можно изменять значения, мне нужно было передать данные в UITableViewController для обновления модели.Для этого я решил использовать делегатский механизм.Итак, я создал протокол с помощью метода, подобного следующему:

- (void)updateData:(DataItem*)dataItem atIndexPath:(NSIndexPath*)index;

UITableViewController реализует этот протокол.Таким образом, в ячейке (по отношению к некоторым событиям) я могу вызвать этот метод и корректно обновить модель.

Сказав это, я хочу задать несколько вопросов:

  1. Это правильный механизм для передачи данных из ячейки в контроллер?
  2. Правильно ли использовать свойство индекса, подобное тому, которое используется в ячейке?
  3. Является ли этото же самое, используя политику сохранения вместо политики копирования.В чем может быть разница?
  4. Поскольку решение, которое я нашел, может быть очень интригующим, возможно ли использовать вместо него блоки?

О блоках я подумал так:

Внутри ячейки создайте блок свойств, подобный следующему:

@property (nonatomic, copy) void (^updateModelOnEvent)(DataItem* dataItem);

Затем внутри метода cellForRowAtIndexPath внутри метода UITableViewController присвойте это свойство коду блока, подобному этому (этот код втот же уровень cell.index = indexPath;):

// configure the cell with the current indexPath
cell.updateModelOnEvent = ^(DataItem* dataItem) {

    [self.model insertObject:dataItem atIndex:indexPath.row];
};

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

Заранее спасибо.

Ответы [ 2 ]

10 голосов
/ 15 февраля 2012

Почему бы просто не использовать [UITableView indexPathForCell:] с делегатом?

MyViewController.h

@interface MyViewController : UITableViewController <MyTableViewCellDelegate>

@end

MyViewController.m

@implementation MyViewController

// methods...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   NSString *reuseIdentifier = @"MyCell";
   MyTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

   if (cell == nil)
       cell = [[[MyTableViewCell alloc] initWithMyArgument:someArgument reuseIdentifier:reuseIdentifier] autorelease];

    [cell setDelegate:self];

    // update the cell with your data

    return cell;
}

- (void)myDelegateMethodWithCell:(MyTableViewCell *)cell {

    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    // update model
}

@end

MyTableViewCell.h

@protocol MyTableViewCellDelegate;

@interface MyTableViewCell : UITableViewCell

@property (assign, nonatomic) id <MyTableViewCellDelegate> delegate;

- (id)initWithMyArgument:(id)someArgument reuseIdentifier:(NSString *)reuseIdentifier;

@end


@protocol MyTableViewCellDelegate <NSObject>

@optional

- (void)myDelegateMethodWithCell:(MyTableViewCell *)cell;

@end

MyTableViewCell.m

@implementation MyTableViewCell

@synthesize delegate = _delegate;

- (id)initWithMyArgument:(id)someArgument reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];

    if (self) {
        // custom setup
    }

    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];

    self.delegate = nil;
}

- (void)someActionHappened {

    if ([self.delegate respondsToSelector:@selector(myDelegateMethodWithCell:)])
        [self.delegate myDelegateMethodWithCell:self];
}

@end
0 голосов
/ 15 февраля 2012
  1. Чтобы изменить ячейки, вы должны изменить модель данных и перезагрузить данные таблицы. Ничего другого.
  2. Не обязательно иметь indexPath для ячейки
  3. В вашем случае это то же самое с использованием политики сохранения или копирования. Копирование создает новые объекты с таким же состоянием.
...