UITableViewCell 在视图生命周期中何时创建它的出口/标签/子视图?

Posted

技术标签:

【中文标题】UITableViewCell 在视图生命周期中何时创建它的出口/标签/子视图?【英文标题】:When in the view lifecycle does UITableViewCell create its outlets/labels/subviews? 【发布时间】:2013-07-27 15:23:55 【问题描述】:

我正在尝试创建一个UIView 作为子类UITableViewCell 的子视图。本质上,我想要一个与单元格大小相同的视图,并且位于单元格的 contentViewbackgroundView 之间。

我想在引擎盖下的某个地方(可能在 layoutSubviews 中),UITableViewCell.m 中有一行类似于:

if (self.contentView != nil) 
    [self addSubview:self.contentView];

如果我想模仿 Apple 的做法,我应该将这段代码放在我自己的自定义 UITableViewCell 子类中的什么位置?

另外,在我第一次尝试的实现中,显示了子视图,但它的默认单元格高度为 44px,而不是我在 tableView:heightForRowAtIndexPath: 中指定的高度。还有其他一些小错误出现,这就是为什么我想尝试复制 Apple 的实现而不是尝试我自己的半功能实现。

编辑:到目前为止,这是我的代码:

CustomTableViewCell.h

interface CustomTableViewCell : UITableViewCell
    @property (nonatomic, strong) UIView *newSubview;
@end

CustomTableViewCell.m

- (void)layoutSubviews 
    [super layoutSubviews];

    if (self.newSubview != nil) 
        self.newSubview.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        [self insertSubview:self.newSubview aboveSubview:self.backgroundView];
    

tableViewController.m

static NSString *CellIdentifier = @"Cell";
myCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) 
    cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


UIView *view = [[UIView alloc] initWithFrame:cell.frame];
view.backgroundColor = [UIColor orangeColor];
cell.newSubview = view;

【问题讨论】:

显示您目前尝试过的内容,您是否设置了自动调整大小的规则? 试过设置autoresizemask,好像没什么区别。我已经发布了我的代码。谢谢 有点跑题了,但我知道一件事——xib 或故事板中的自动调整大小真的把这些东西搞砸了。 【参考方案1】:

一般来说,对象应该在它们指定的初始化器中创建它们的属性,除非有一个压倒一切的设计原则(或性能/资源问题)要求它们稍后再创建它们。

UIView(和 OS X 上的 NSView)的指定初始化程序是 -initWithFrame:UITableView 的指定初始化程序是 initWithFrame:style:。由于视图通常需要在添加到其父视图后立即使其可见的子视图可用,因此可以在指定的初始化程序中创建和设置它们。

-layoutSubviews 用于更新布局,即中心、边界(或框架)和(可选)变换。现在,由于消息的排序。您不想在 -layoutSubviews 中创建子视图,因为该方法在视图的生命周期内被重复调用,因为它的父视图的边界发生了变化,并且它被删除或重新添加到它的父视图,或者它的子视图改变。

在 UITableView 的情况下,每次重新加载表格时都会调用-layoutSubviews

此规则的一个典型例外是创建用作表行的UITableViewCells,必须动态创建。

-heightForRowAtIndexPath 方法提供了一个表格视图,其中包含它需要为该行的单元格留出的空间量,但实际上并不会导致单元格被调整大小。您必须在创建单元格时自己设置单元格的边界(或者单元格可以在-initWithStyle:reuseIdentifier: 中设置自己的边界,如果它被设计为固定值)。如果您的单元格大小与表格的预期不符,则会出现间隙或重叠。

要使自动调整大小的蒙版正常工作,您必须自己配置视图的初始帧(在代码中或在 nib 中)。自动调整视图大小会影响它如何响应其父视图边界中的更改,但无助于确定视图的初始帧。

具体来说,您必须为单元格的子视图设置初始帧(并确保同级子视图排序等)。这在 nib 中比在代码中更容易做到。

【讨论】:

感谢您的详细回复。那么,鉴于在我的 CustomTableViewCell 的指定初始化程序中,子视图尚不知道,是否可以使用 layoutSubviews 中的 [insertSubview: aboveSubview:] 方法? 当然。视图层次结构旨在支持动态操作。这就是让它们如此美妙的部分原因。您可以根据需要添加和删除子视图。但是,管理视图层次结构在概念上与管理视图布局有很大不同。也许有一个更自然的地方可以添加和删除视图,就任何正在更改的属性导致您想要添加或删除视图而言。例如,表视图可能会在其内容更改时添加/删除子视图(在 -reloadData 中),然后在单独的步骤中将它们布置。 另外,我的newSubview 的大小不正确,但单元格的backgroundViewselectedBackgroundView 的大小正确,即使这三个都以相同的方式初始化:initWithFrame:cell.frame。这表明某些视图在创建后会调整大小。我是否可以为我自己的自定义单元格视图复制此过程? 好吧,我可能错了,内容视图的大小没有被表格视图改变。人们应该始终检验自己的假设! 哈哈,这可能是值得进一步研究的东西。最后,我决定在创建可重用单元格时手动设置子视图的高度 - 一个不太优雅但仍然可行的解决方案。

以上是关于UITableViewCell 在视图生命周期中何时创建它的出口/标签/子视图?的主要内容,如果未能解决你的问题,请参考以下文章

应用与视图的生命周期和方法调用

Android视图动画生命周期

在视图控制器生命周期中添加子视图的位置

如何响应 SwiftUI 中的视图生命周期事件?

视图控制器的生命周期(精简)

在 UIView 生命周期中知道何时销毁视图