为什么我的UITableViewCell的宽度与我的UITableView的宽度不同?

时间:2014-05-03 13:42:52

标签: ios objective-c xcode uitableview

问题是:我有一个自定义表格视图单元格,由表格视图使用,而表格视图又是通用的。该表视图的宽度通过IB设置为240。假设单元格的宽度与表格的宽度相同,我继续添加一些逻辑来计算图像视图和两个标签的范围,然后将这两个标签添加到单元格的内容视图中。事实证明,我的假设是错误的。 试图发现什么是错的,我继续并重写了tableView:willDisplayCell:forRowAtIndexPath:。问题是这个方法显示单元格的宽度将是所需的240个点,但它会在自定义单元格initWithStyle:reuseIdentifier:的指定初始化之后被调用,奇怪的是,它返回320个点。

以下是细胞的初始化:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        NSLog(@"cell frame at init: %@", NSStringFromCGRect(self.contentView.frame));
        self.avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.height, self.contentView.frame.size.height)];
        [self.contentView addSubview:self.avatarView];

        self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.avatarView.frame.size.width + 10, 0, self.frame.size.width - self.avatarView.frame.size.width - 40, self.frame.size.height)];
        self.nameLabel.backgroundColor = [UIColor greenColor];
        [self.contentView addSubview:self.nameLabel];

        self.visitorsLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.avatarView.frame.size.width + self.nameLabel.frame.size.width + 20, 0, self.frame.size.width - (self.avatarView.frame.size.width + self.nameLabel.frame.size.width + 20), self.contentView.frame.size.height)];
        self.visitorsLabel.textColor = [UIColor whiteColor];
        self.visitorsLabel.backgroundColor = [UIColor redColor];
        [self.contentView addSubview:self.visitorsLabel];
    }
    return self;
}

子视图的信息以不同的方式提供。 这是控制器中的代码,表视图的委托:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NewClubTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"newCell"];
    Club *club = [self.clubs getClubAtIndex:indexPath.row];
    cell = [[NewClubTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"newCell"];
    [cell setAvatar:club.avatar name:club.name visitors:club.visitors];

    return cell;
}

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"table view will display frame: %@", NSStringFromCGRect(cell.frame));
}

这是日志的结果:

2014-05-03 16:18:04.143 FanStation[2436:70b] cell frame at init: {{0, 0}, {320, 44}}
2014-05-03 16:18:04.144 FanStation[2436:70b] table view will display frame: {{0, 0}, {240, 44}}
2014-05-03 16:18:04.145 FanStation[2436:70b] cell frame at init: {{0, 0}, {320, 44}}
2014-05-03 16:18:04.146 FanStation[2436:70b] table view will display frame: {{0, 44}, {240, 44}}
2014-05-03 16:18:04.146 FanStation[2436:70b] cell frame at init: {{0, 0}, {320, 44}}
2014-05-03 16:18:04.147 FanStation[2436:70b] table view will display frame: {{0, 88}, {240, 44}}
2014-05-03 16:18:04.147 FanStation[2436:70b] cell frame at init: {{0, 0}, {320, 44}}
2014-05-03 16:18:04.148 FanStation[2436:70b] table view will display frame: {{0, 132}, {240, 44}}
2014-05-03 16:18:04.148 FanStation[2436:70b] cell frame at init: {{0, 0}, {320, 44}}
2014-05-03 16:18:04.149 FanStation[2436:70b] table view will display frame: {{0, 176}, {240, 44}}

正如您所看到的,表格视图提供了正确的宽度,但是单元格仍然有自己的想法。

我的问题是,如果我在这里做错了,是否有办法纠正这个问题? 如果您需要有关此案例的任何其他信息,我将非常乐意提供此信息。

2 个答案:

答案 0 :(得分:12)

表格视图单元格不知道它的初始值设定项应该是多少。它以默认大小(320点)初始化,然后在显示之前调整大小。不要注意init方法中设置的大小。

你所看到的是完全正常的。

您将在视图控制器中看到与主视图相同的内容。视图在viewDidLoad中以其默认大小和方向创建,然后调整大小并旋转以供显示。

编辑:

如果需要在调整单元格大小时收到通知,则可以实现视图控制器方法didLayoutSubViews。当单元格在初始化后初始化为表视图的大小时,以及在视图控制器的内容视图的大小发生变化之后(例如,在设备旋转之后),将调用它。

答案 1 :(得分:4)

在与@Duncan C和@Basheer_CAD进行非常有益的讨论后,我觉得有必要详细说明我在当前帖子中提出的问题的解决方案。 如果我在单元格外部进行任何UITableViewCell子视图初始化,我认为这将是犯规。因此,按照上面提到的两个建议,我继续覆盖了单元格layoutSubviews,在那里我创建了子视图的rects。事实证明,layoutSubviews很晚才到达现场,渲染我的方法为子视图提供的信息毫无用处。所以我不得不创建其他属性来临时存储图像和两个字符串。然后在初始化子视图的过程中使用它们。 同样,这是控制器中的代码,如果你按照数字,你将得到序列:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NewClubTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"newCell"];
    Club *club = [self.clubs getClubAtIndex:indexPath.row];
(1)
    cell = [[NewClubTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"newCell"];
(3)
    [cell setAvatar:club.avatar name:club.name visitors:club.visitors];

    return cell;
}

这是单元格的初始化程序。如你所见,它什么都不做:

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier avatar:(UIImage *)avatar name:(NSString *)name visitors:(NSInteger)visitors
{
(2)
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

    }

    return self;
}

数据传输方法:

-(void)setAvatar:(UIImage *)avatar name:(NSString *)name visitors:(NSInteger)visitors
{
    (4)
    self.avatarImage = avatar;
    self.name = name;
    self.visitors = [NSString stringWithFormat:@"%d", visitors];
}

最后,layoutSubviews

-(void)layoutSubviews
{
(5)
    self.avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.height, self.contentView.frame.size.height)];
    self.avatarView.image = self.avatarImage;
    [self.contentView addSubview:self.avatarView];

    self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.avatarView.frame.size.width, 0, self.frame.size.width - self.avatarView.frame.size.width - 40, self.frame.size.height)];
    self.nameLabel.text = self.name;
    self.nameLabel.backgroundColor = [UIColor greenColor];
    [self.contentView addSubview:self.nameLabel];

    self.visitorsLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.avatarView.frame.size.width + self.nameLabel.frame.size.width, 0, self.frame.size.width - (self.avatarView.frame.size.width + self.nameLabel.frame.size.width), self.contentView.frame.size.height)];
    self.visitorsLabel.text = self.visitors;
    self.visitorsLabel.textColor = [UIColor whiteColor];
    self.visitorsLabel.backgroundColor = [UIColor redColor];
    [self.contentView addSubview:self.visitorsLabel];
}

它的美妙之处在于,无论设备及其方向如何,生命周期中只有一种方法是使整个事物正常运行并正确显示的关键。