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

发布于 2024-12-29 02:13:47 字数 2127 浏览 2 评论 0原文

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

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

这就是场景。首先,我创建了一个名为 DataTableViewCell 的自定义单元格(与 xib 接口关联),它扩展了 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. 由于我找到的解决方案可能非常诡计多端,是否可以使用 block 来代替?

关于块,我是这样想的:

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

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

然后在UITableViewController内的cellForRowAtIndexPath方法内将该属性分配给一个块代码,如下所示this(此代码与 cell.index = indexPath; 处于同一级别):

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

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

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

先感谢您。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜声 2025-01-05 02:13:47

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

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
水水月牙 2025-01-05 02:13:47
  1. 要修改单元格,您应该修改数据模型并重新加载表数据。没有别的了。
  2. 单元格不需要有索引路径
  3. 在您的情况下,使用保留或复制策略是相同的。复制使新对象具有相同的状态。
  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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文