在 UITableViewCell 中使 UIView 出队

Posted

技术标签:

【中文标题】在 UITableViewCell 中使 UIView 出队【英文标题】:Dequeueing UIViews withing UITableViewCell 【发布时间】:2012-05-01 06:52:01 【问题描述】:

在使用 UITableView 的正常情况下,我有重用旧单元格的标准代码:

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

    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
    return cell;

然而,我注意到,当我将子视图添加到单元格时,它们并没有被删除,并且每次都会添加一个新视图。我在下面有一个例子可以完美地展示它:

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

    static NSString *cellIdentifier = @"Cell";

    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    UILabel *label = [[UILabel alloc] init];
    label.text = @"HELLO";
    label.frame = CGRectMake(arc4random() % 50, -1, 286, 45);
    label.backgroundColor = [UIColor clearColor];

    // Add views
    [cell addSubview:label];

    return cell;

我需要一些代码来再次重用我的标签,就像重用单元格一样。我该怎么办?

谢谢

【问题讨论】:

添加到单元格后只需释放标签即可。 删除标签或注释 if(cell==nil) 条件行。因此它会分配每个新单元格。它将彻底解决您的问题,但对大表有内存管理问题。 【参考方案1】:

只有在创建新单元格时才必须添加子视图。如果您正在出队,则子视图已经存在,不应重新创建。

你的方法应该是:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath 
 
    static NSString *cellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:cellIdentifier]; 
    UILabel *label;
    if (cell == nil) 
    
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
        label = [[UILabel alloc] init];
        label.tag = 1;
        // Add views 
        [cell addSubview:label];
    
    else
    
        // Label will already exist, get a pointer to it
        label = [cell viewWithTag:1];
    

    // Now set properties on the subview that are unique to each cell
    label.text = @"HELLO"; 
    label.frame = CGRectMake(arc4random() % 50, -1, 286, 45); 
    label.backgroundColor = [UIColor clearColor]; 

    return cell; 
 

请注意标签是如何仅在单元格为 nil 时创建的。否则,使用标签找到它。

【讨论】:

谢谢,真的很有帮助。这就是我认为我需要处理它但不知道如何编写它的方式。【参考方案2】:

我需要一些代码以与单元格相同的方式再次重用我的标签 正在被重复使用。

不,您需要更好地了解表格视图设计。为什么视图被多次添加应该很明显——重用一个单元意味着你使用一个不再需要的 UITableViewCell 的先前实例(从而节省了新对象的昂贵分配)并将这个实例重用于新单元.但是这个前面的实例已经附加了标签,所以标签的数量增加了。

我将子类化UITableViewCell 并将标签创建放在这个新类的初始化代码中。 (或者创建一个UIView 子类并将其设置为单元格的contentView,正如nice table tutorial by Matt Gallagher 中所建议的那样。)这是封装视图详细信息并将其隐藏在表数据源中的正确方法。

【讨论】:

【参考方案3】:

您可以在 else 部分中使用类似 if(cell == nil)

的内容
for (UIView *sub in [cell.contentView subviews]) 

            if([UILabel class] == [sub class])
                NSLog(@"%@",[sub class]);
                UILabel *label = (UILabel *)sub;
                //do label coding ie set text etc.

【讨论】:

【参考方案4】:

我在我的自定义表格单元类中使用延迟初始化视图。 它只需要加载视图和“addSubview”一次。

- (void) lazyInitTitleLabel 
    if (_titleLabel != nil) 
        return;
    

    _titleLabel = [[UILabel alloc] initWithFrame: CGRectMake(10.0f, 10.0f, 200.0f, 30.0f)];
    // Cell adds the label as a subview...
    [self addSubview: _titleLabel];

您唯一需要注意的是重置视图显示的任何内容,例如标签中的文本和图像视图中的图像。如果您不这样做,旧内容可能会与回收的表格单元格一起重复使用。

祝你好运!

【讨论】:

以上是关于在 UITableViewCell 中使 UIView 出队的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 子类,错误的高度直到滚动

在代码中使两个 AutoLayout 约束相等?

如何在 Objective-C 的 UITableView 中使 UITableViewRowAction 完全透明

iOS - subivew 不能在 UITableViewCell 中居中

UITableViewCell 中的 UITextField 与 UIPickerView?

在代码中自动调整 UIImageView