将数据从UITableViewCell传递到UITableViewController的配方

时间:2012-01-25 15:15:51

标签: ios protocols uitableview objective-c-blocks

我正在找出将数据从UITableViewCell传递到UIableViewController(或UIViewController)的正确机制。

在stackoverflow中搜索我找到了不同的方法来做到这一点,最后我找到了一个运行良好的机制,但我不知道它是否是一个有效的方法。

这就是场景。首先,我创建了一个名为DataTableViewCell的自定义单元格(与xib接口关联),扩展了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. 由于我发现的解决方案可能非常有计划,是否可以使用block而不是?
  5. 关于街区,我这么想:

    在单元格内创建一个属性块,如下所示:

    @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 个答案:

答案 0 :(得分:10)

为什么不将[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

答案 1 :(得分:0)

  1. 要修改单元格,您应修改数据模型并重新加载表格数据。没别了。
  2. 没有必要为cell
  3. 设置indexPath
  4. 在您的情况下,使用保留或复制政策是相同的。复制使新对象具有相同的状态。