【问题标题】:Recipes to pass data from UITableViewCell to UITableViewController将数据从 UITableViewCell 传递到 UITableViewController 的方法
【发布时间】:2012-01-25 15:15:51
【问题描述】:

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

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

这就是场景。首先,我创建了一个自定义单元格(与 xib 接口相关联),名为 DataTableViewCell,它扩展了 UITableViewCell。这个单元格有一些显示(和修改)数据的出口和一个称为索引的成瘾属性,如下所示:

@property (nonatomic, copy) NSIndexPath* index;

该属性在UITableViewController内的方法cellForRowAtIndexPath内刷新:

- (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);

然后在UITableViewController中的方法cellForRowAtIndexPath方法内将该属性分配给这样的块代码(此代码与cell.index = indexPath;处于同一级别):

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

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

可能是一个有效的替代方案吗?在这种情况下,我必须使用复制或保留政策吗?

提前谢谢你。

【问题讨论】:

    标签: ios protocols uitableview objective-c-blocks


    【解决方案1】:

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

    【讨论】:

    • 好的,但是如何将数据表单单元格传递给控制器​​?通过您的代码是不可能的。谢谢。
    • 这个想法是你有一个带有委托回调的单元格,我会在我的答案中添加更多代码。
    • 感谢您的详细回答。这有助于我更好地理解代表。
    【解决方案2】:
    1. 要修改单元格,您应该修改数据模型并重新加载表格数据。没有别的了。
    2. 不必为单元格设置 indexPath
    3. 在您的情况下,使用保留或复制策略是相同的。复制使新对象具有相同的状态。

    【讨论】:

    • 他想从单元格中更新他的模型(可能是从单元格中的控件或其他东西),而不是更新表格视图以反映模型更改。
    猜你喜欢
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多