使用子视图重用单元格(以编程方式)

Posted

技术标签:

【中文标题】使用子视图重用单元格(以编程方式)【英文标题】:Reuse Cell with Subview (programmatically) 【发布时间】:2011-06-14 01:21:22 【问题描述】:

我在以编程方式将子视图添加到 UITableView 单元格时遇到问题。我正在尝试将 UITextFiled 添加到 2 个单元格,并将 UILabel 添加到表的一个部分中的另一个单元格。该表有 3 个部分,其中大部分是手动创建的。其中一个单元格在被选中时会调用一个插入另外四个单元格的操作。如果再次选择相同的单元格,则将删除四个单元格。发生此操作时,子视图会混淆并位于错误的单元格上。键盘也不响应完成键。

我尝试在 if (cell == nil) 条件语句中创建子视图。这是我创建单元格的代码(抱歉,它太乱了,我尝试了很多东西):

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

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) 
    NSLog(@"cell created");
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    if (indexPath.section == 0 && indexPath.row == 0 && ([cellText objectAtIndex:indexPath.row] == @"Weight")) 
        exerciseWeight = [[[UITextField alloc] initWithFrame:CGRectMake(0, 12, 295, 30)] autorelease];
        exerciseWeight.textAlignment = UITextAlignmentRight;
        exerciseWeight.adjustsFontSizeToFitWidth = YES;
        exerciseWeight.textColor = [UIColor blackColor];
        exerciseWeight.backgroundColor = [UIColor clearColor];
        exerciseWeight.tag = 89899;
        exerciseWeight.keyboardType = UIKeyboardTypeNumberPad;
        [exerciseWeight setReturnKeyType:UIReturnKeyDone];
        exerciseWeight.clearButtonMode = UITextFieldViewModeNever;
        [exerciseWeight setEnabled: YES];
        [exerciseWeight setDelegate:self];
        [cell addSubview:exerciseWeight];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.accessoryType = UITableViewCellAccessoryNone;

     else if (indexPath.section == 0 && indexPath.row == 1) 
        NSLog(@"Created metric subview");
        metric = [[[UILabel alloc] initWithFrame:CGRectMake(100, 5, 180, 30)] autorelease];
        metric.textAlignment = UITextAlignmentRight;
        metric.textColor = [UIColor grayColor];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        metric.tag = 89898;
        [cell addSubview:metric];
     else if (([cellText count] - 1) == indexPath.row)
        exerciseReps = [[[UITextField alloc] initWithFrame:CGRectMake(0, 12, 295, 30)] autorelease];
        exerciseReps.textAlignment = UITextAlignmentRight;
        exerciseReps.adjustsFontSizeToFitWidth = YES;
        exerciseReps.backgroundColor = [UIColor clearColor];
        exerciseReps.tag = 89890;
        exerciseReps.keyboardType = UIKeyboardTypeNumberPad;
        [exerciseReps setReturnKeyType:UIReturnKeyDone];
        exerciseReps.clearButtonMode = UITextFieldViewModeNever;
        [exerciseReps setEnabled:YES];
        [exerciseReps setDelegate:self];
        [cell addSubview:exerciseReps];
     else if (indexPath.section == 2) 
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
 else 
    exerciseWeight = (UITextField *)[cell viewWithTag:89899];
    metric = (UILabel *)[cell viewWithTag:89898];
    exerciseReps = (UITextField *)[cell viewWithTag:89890];

if (indexPath.section == 0) 
    cell.textLabel.text = [cellText objectAtIndex:indexPath.row];

// Configure the cell...
if (indexPath.section == 0 && indexPath.row == 0) 
    cell.textLabel.textAlignment = UITextAlignmentLeft;
    exerciseWeight.placeholder = @"160";


 else if (indexPath.section == 0 && indexPath.row == 1) 
    metric.text = metricUnit;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 else if (cell.textLabel.text == @"Repetitions")
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.accessoryType = UITableViewCellAccessoryNone;
    exerciseReps.placeholder = @"10";
 else if (indexPath.section == 1) 
    cell.textLabel.text = @"Log New Set";
    cell.textLabel.textAlignment = UITextAlignmentCenter;
    cell.accessoryType = UITableViewCellAccessoryNone;
 else if (indexPath.section == 2) 
    cell.textLabel.text = @"History";

 else if (cell.textLabel.text == @"  Pounds") 
    cell.textLabel.textColor = [UIColor grayColor];
    cell.textLabel.font = [UIFont systemFontOfSize:14];
 else if (cell.textLabel.text == @"  Kilograms") 
    cell.textLabel.textColor = [UIColor grayColor];
    cell.textLabel.font = [UIFont systemFontOfSize:14];
 else if (cell.textLabel.text == @"  Miles") 
    cell.textLabel.textColor = [UIColor grayColor];
    cell.textLabel.font = [UIFont systemFontOfSize:14];
 else if (cell.textLabel.text == @"  Kilometers") 
    cell.textLabel.textColor = [UIColor grayColor];
    cell.textLabel.font = [UIFont systemFontOfSize:14];


return cell;

// [exerciseWeight release];
// [metric release];
// [exerciseReps release]; 

【问题讨论】:

【参考方案1】:

看起来你会在这里玩得开心。但是一旦你完成了它会很令人满意:-)

我不确定您发布的代码是否是您需要担心的问题。定义您在表中看到的内容(主要)是诸如 heightForRowAtIndexPath、numberOfSectionsInTableView 和 numberOfRowsInSection 之类的方法。如果你做对了,你会得到你想要的显示。因此,当您点击一个单元格时,您将修改您的底层数据结构,然后调用 reloadData - 导致表格视图再次调用这些方法。

关于布置这些单元格,我根本看不到您使用单元格的 contentView。你看过 Cocoa With Love 博客吗,特别是 Easy custom UITableView drawing 和 UITableView construction, drawing and management (revisited)?我还使用了 Apple 文档Table View Programming Guide for ios 中描述的定义表格视图单元格的 xib 方法,并且鉴于 Xcode 不断改进界面构建器与代码的交互的方式可能会继续这样做。我非常反对 IB,但现在看到了使用它的价值,因为 Xcode 4 消除了切换应用程序使用它的痛苦,犯错的机会要少得多。

我的想法是,当您“添加视图”到单元格时,您应该只切换到您定义的另一个单元格并根据需要在 reloadData 之后加载该单元格。当您想要添加单元格时,您需要更改基础数据结构并让表格自行显示。

关于单元格标识符的问题 - 您可以使用一个单元格标识符并仅节省创建单元格的成本,将您对所有单元格所做的所有常见操作都考虑在内,或者您可以为每种类型创建具有唯一标识符的单元格当您的部分/行表明需要 TK421 时,单元格和重用单元格变体 TK421。我倾向于做第二个。我实际上不知道哪个性能更好,但我敢肯定,任何一个都比不重复使用要好。

【讨论】:

感谢您的回复,亚当!我最终为每种类型的单元格添加了唯一标识符。我不确定这是否是内存管理的最佳方式。由于我只有 7 个单元格和 3 种类型,我认为使用重用标识符保存的内存不需要完美。我在访问具有文本字段的子视图时确实遇到了一些问题——我通过循环遍历文本字段类以找到具有正确标签的文本字段来解决这个问题。再次感谢您的帮助!

以上是关于使用子视图重用单元格(以编程方式)的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式设置 UICollectionViewController 单元格内的 UIView 子视图的高度?

以编程方式将按钮添加到表格视图单元格[关闭]

以编程方式向表格视图单元格添加按钮[关闭]

重用 uitableview 单元格以及单元格中的子视图

如何使用故事板中定义的单元格计算集合视图单元格高度?

以编程方式创建形状视图并在集合视图单元格上使用