Recipes to pass data from UITableViewCell to UITableViewController

旧巷老猫 提交于 2019-12-01 07:32:36

问题


I'm figuring out the right mechanism to pass data from UITableViewCells to a UIableViewController (or UIViewController).

Searching within stackoverflow I found different ways to do this and finally I found a mechanism that works well but I don't know if it could be a valid approach.

This is the scenario. First, I created a custom cell (associated with a xib interface), named DataTableViewCell, that extends UITableViewCell. This cell has some outlet to display (and modify) data and an addictional property called index like the following:

@property (nonatomic, copy) NSIndexPath* index;

This property is refreshed inside the method cellForRowAtIndexPath method within the 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;
}

Since it is possible to change values within a cell, I had the need to pass data to the UITableViewController for updating the model. To do that I decided to use a delegate mechanism. So, I created a protocol with a method like the following:

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

The UITableViewController implements that protocol. In this way, within the cell (against to some events), I can call that method and update the model in the correct way.

Having said this, I have some questions to ask:

  1. Is this a right mechanism to pass data from a cell to a controller?
  2. Is it correct to using an index property like the one use in the cell?
  3. Is it the same using retain policy instead of copy policy. What could be the difference?
  4. Since the solution I found could be very scheming, is it possible to use block insteads?

About blocks, I thought this way:

Within the cell create a property block like the following:

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

Then inside the method cellForRowAtIndexPath method within the UITableViewController assign that property to a block code like this (this code is at the same level of cell.index = indexPath;):

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

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

Could be a valid alternative? In this case, do I have to use copy or retain policy?

Thank you in advance.


回答1:


Why not just use [UITableView indexPathForCell:] with a delegate?

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



回答2:


  1. To modify cells you should modify data model and reload table data. Nothing else.
  2. Not necessary to have a indexPath for cell
  3. In your case it is the same using retain or copy policy. Copy makes new objects with same state.


来源:https://stackoverflow.com/questions/9005052/recipes-to-pass-data-from-uitableviewcell-to-uitableviewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!