首次加载 UITableViewController 时自定义 UITableViewCell 无法正确显示

Posted

技术标签:

【中文标题】首次加载 UITableViewController 时自定义 UITableViewCell 无法正确显示【英文标题】:Custom UITableViewCell not displaying correctly when UITableViewController first loads 【发布时间】:2012-02-10 11:14:30 【问题描述】:

我使用以下代码创建了一个自定义 UITableViewCell:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 

        mapButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];       
        [[self contentView] addSubview:mapButton];        

        houseNumberLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        [[self contentView] addSubview:houseNumberLabel];
        [houseNumberLabel release];

        NSArray *segmentArray = [[NSArray alloc] initWithObjects:@"Yes", @"No", nil];
        segmentedControl = [[UISegmentedControl alloc] initWithItems:segmentArray];
        [segmentArray release];
        [segmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar];
        [[self contentView] addSubview:segmentedControl];
        [segmentedControl release];

        disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
        [[self contentView] addSubview:disclosureButton];              
    

    return self;

然后,我使用以下代码覆盖了自定义单元格中的 layoutSubviews 方法:

- (void)layoutSubviews

    [super layoutSubviews];

    CGRect viewBounds = [[self contentView] bounds];
    float h = viewBounds.size.height;
    float w = viewBounds.size.width;

    float inset = 20.0;
    float mapButtonWidth = mapButton.frame.size.width;
    float segmentWidth = 140.0;
    float disclosureButtonWidth = disclosureButton.frame.size.width;
    float houseNumberLabelWidth = viewBounds.size.width - (mapButtonWidth + inset + inset + segmentWidth + inset + disclosureButtonWidth + inset);

    CGRect frame = CGRectMake(0, 0, h, mapButtonWidth);
    [mapButton setFrame:frame];

    frame.origin.x += mapButtonWidth + inset;
    frame.size.width = houseNumberLabelWidth;
    [houseNumberLabel setFrame:frame];

    frame.origin.x += houseNumberLabelWidth + inset;
    frame.size.width = segmentWidth;
    [segmentedControl setFrame:frame];

    frame.origin.x += segmentWidth + inset;
    frame.size.width = disclosureButtonWidth;
    [disclosureButton setFrame:frame];

我已将日志添加到这些函数中,并且每次创建单元格时都会调用它们。问题是当 UITableViewController 第一次加载并显示单元格时,单元格显示的格式就像从未调用过 layoutSubviews 一样(即使根据它拥有的日志)。但是,当我滚动表格视图时,新单元格(不在屏幕上)会正确显示。然后我向后滚动,第一个单元格现在是正确的。就好像 layoutSubviews 正在被调用,但是当第一次加载表格视图时,它没有意识到它需要使用新布局进行渲染。

我已经向 viewWillAppear 添加了一个 reloadData,它部分地解决了问题,但是最后一个单元格(即在屏幕外)仍然呈现不正确的方式。我正在拔头发。

[SUBNOTE] 我刚刚添加了一个日志:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

在调用 layoutSubviews 之前,它运行了 8 次(每个单元格首先为表格视图显示一个)。在此之后调用 layoutSubviews (因此格式不正确)。我应该在这里添加一个 [cell layoutSubviews](它确实有效,但之后会再次调用它)还是有其他方法?

【问题讨论】:

那么,你在willDisplayCell 中做了什么导致这种情况?我建议在cellForRowAtIndexPath 中尽可能多地设置单元格,或者您在willDisplayCell 中调用单元格的任何方法都应该调用setNeedLayout,如果更改该数据意味着它需要布局。 【参考方案1】:

我解决了(我对这个错误有点尴尬)但我最初设置的 CGRect 尺寸不正确。我将高度作为宽度,将宽度作为高度。代码应该是:

CGRect frame = CGRectMake(0, 0, mapButtonWidth, h);

一个很容易犯的错误,但会产生不寻常的结果。

【讨论】:

以上是关于首次加载 UITableViewController 时自定义 UITableViewCell 无法正确显示的主要内容,如果未能解决你的问题,请参考以下文章

iPhone简介视图-仅在首次加载时加载[关闭]

我可以在初始加载视图时旋转 tableview UIRefreshControl(活动指示器),而无需用户向下滑动吗?

vue首次加载网页的loading

首次加载时动画滞后

iPhone 应用首次加载查询时的动画

PF QueryCollection ViewController 中首次加载时未出现图像