问题
I'm figuring out the right mechanism to pass data from UITableViewCell
s 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:
- Is this a right mechanism to pass data from a cell to a controller?
- Is it correct to using an index property like the one use in the cell?
- Is it the same using retain policy instead of copy policy. What could be the difference?
- 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:
- To modify cells you should modify data model and reload table data. Nothing else.
- Not necessary to have a indexPath for cell
- 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