iOS - UITableviewCell的子视图不重新加载/更新

时间:2014-04-03 04:27:49

标签: ios objective-c uitableview subview reloaddata

我有一个表视图,其中的单元格创建如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    cell.textLabel.text = @"TempTitle";

    cell.textLabel.font = [UIFont fontWithName: @"AppleSDGothicNeo-Bold" size:16.0];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];

    UILabel *numberLabel = [[UILabel alloc] init];
    [numberLabel setFrame:CGRectMake(230.0, 5.0, 40.0, 30.0)];
    [numberLabel setText:[NSString stringWithFormat:@"%@", [self.arrayOne objectAtIndex:indexPath.row]]];

    UIButton *buttonDown = [[UIButton alloc] init];
    [buttonDown setFrame:CGRectMake(190.0, 5.0, 40.0, 30.0)];
    buttonDown.tag = indexPath.row;
    [buttonDown addTarget:self action:@selector(quantityDown:) forControlEvents:UIControlEventTouchUpInside];

    UIButton *buttonUp = [[UIButton alloc] init];
    [buttonUp setFrame:CGRectMake(270.0, 5.0, 40.0, 30.0)];

    [cell addSubview:buttonDown];
    [cell addSubview:numberLabel];
    [cell addSubview:buttonUp];

    return cell;
}

其中self.arrayOne(此线程的名称已更改)包含每个单元格中显示的整数值。选择buttonDown时的方法如下:

- (void) quantityDown:(id)sender {
    int clicked = ((UIButton *)sender).tag;

    ... math to lower int by one and save the new value in arrayOne
    ... this part works just fine. The value does go down, as intended.

    [self.tableView reloadData];
}

当tableView重新加载时,新标签会打印在该单元格中现有标签的顶部,如下图所示:

Screen shot

我只能假设新按钮也打印在现有按钮之上。这既昂贵又使得数字不可读(特别是如果你多次改变它!)。离开视图并返回到它会干净地显示新数字,但只有在您再次开始更改它们之前。

当我在顶部使用UISegmentedControl时会发生类似的效果。选择一个或另一个会更改表的内容并运行[self.tableView reloadData]。调用此方法时,每个单元格的textLabel都会重新加载,但子视图不会重新加载,而是相互堆叠。

我如何写这个,以便每个单元格中只有一个子视图,而不是多个堆叠在一起?快速而且资源不贵的东西。也许删除所有子视图,然后添加新的子视图?我试过像

这样的东西
[[cell.contentView viewWithTag:tagVariable]removeFromSuperview];

无济于事。实际上,我只需要修改用户点击的表中的一个单元格。除了用户在顶部使用UISegmentedControl时,所有单元格都需要修改。

提前致谢。

编辑1:

创建了一个自定义的UITableViewCell类......

@interface SSCustomTableViewCell : UITableViewCell

@property (nonatomic) UILabel *quantity;
@property (nonatomic) UIButton *down;
@property (nonatomic) UIButton *up;

@end

@implementation SSWeightsTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.quantity = [UILabel new];
        [self.contentView addSubview:self.quantity];
        self.down = [UIButton new];
        [self.contentView addSubview:self.down];
        self.up = [UIButton new];
        [self.contentView addSubview:self.up];
    }
    return self;
}

- (void) layoutSubviews {
    [super layoutSubviews];

    [self.down setFrame:CGRectMake(190.0, 5.0, 40.0, 30.0)];
    [self.down setBackgroundColor:[UIColor purpleColor]];

    [self.up setFrame:CGRectMake(270.0, 5.0, 40.0, 30.0)];
    [self.up setBackgroundColor:[UIColor purpleColor]];

    [self.quantity setFrame:CGRectMake(230.0, 5.0, 40.0, 30.0)];
    [self.quantity setTintColor:[UIColor purpleColor]];
}

@end

然后在我的UITableView类中......

#import "SSCustomTableViewCell.h"

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.tableView
     registerClass:[SSCustomTableViewCell class]
     forCellReuseIdentifier:NSStringFromClass([SSCustomTableViewCell class])
     ];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    UITableViewCell *cell = [tableView 
                             dequeueReusableCellWithIdentifier: NSStringFromClass([SSWeightsTableViewCell class])
                             forIndexPath:indexPath
                             ];
}

但现在我所看到的只有以下内容......

new screen show

子视图的布局不正确,大小也不正确。此外,在cellForRowAtIndexPath方法中,我无法访问单元格的组件。当我进入

cell.quantity

我收到一条错误,说“在UITableViewCell *类型的对象上找不到”属性'数量'

所以我试过

SSCustomTableViewCell *cell = [tableView 
                             dequeueReusableCellWithIdentifier: NSStringFromClass([SSWeightsTableViewCell class])
                             forIndexPath:indexPath
                             ];

并且错误消失了,但是当我运行它时它仍然看起来一样。

编辑2:工作解决方案

我所要做的只是添加

cell = [[UITableViewCell alloc]init];

cellForRowAtIndexPath方法中。其他所有内容保持不变,不需要自定义类。

2 个答案:

答案 0 :(得分:5)

您看到此错误,因为重用了单元格实例。如果每次配置单元格时都添加视图,则将添加已经包含子视图的单元格。您应该创建自己的UITableViewCell子类,并在init中添加子视图。那么上面的方法只会在各个子视图上设置值。

你的手机看起来像这样:

@interface MyCustomCell : UITableViewCell

@property (nonatomic, strong) UILabel *myCustomLabel;

@end

@implementation MyCustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.myCustomLabel = [UILabel new];
        [self.contentView addSubview:self.myCustomLabel];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    // Arrange self.myCustomLabel how you want
}

@end

然后您的视图控制器将如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.tableView
        registerClass:[MyCustomCell class]   
        forCellReuseIdentifier:NSStringFromClass([MyCustomCell class])
     ];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
        dequeueReusableCellWithIdentifier:NSStringFromClass([MyCustomCell class])      
        forIndexPath:indexPath
    ];
    cell.myCustomLabel.text = @"blah";
    return cell;
}

答案 1 :(得分:0)

在单元格配置方法中尝试此操作,这将确保对象不重叠

for (UIView *subview in [cell.contentView subviews]) {
    [subview removeFromSuperview];
}

示例:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = @"cellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell==nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];

}

for (UIView *subview in [cell.contentView subviews]) {
    [subview removeFromSuperview];
}

return cell;
}

希望这会有所帮助