UITableViewCell 的初始化在哪里?

Posted

技术标签:

【中文标题】UITableViewCell 的初始化在哪里?【英文标题】:Where are the UITableViewCell's initialized? 【发布时间】:2014-02-13 19:52:15 【问题描述】:

我创建了自己的CustomTableViewCustomCell。单元格在xib 中,我在初始化tableView 时正在注册它,如下所示:

[self registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] 
                    forCellReuseIdentifier:kCustomCellIdentifier];

如果我不这样做,我将无法定义 ReuseIdentifier 应该“指向”这个类的内容。这是我的cellForRow

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

    CustomCell *cell = [self dequeueReusableCellWithIdentifier:
                        kCustomCellIdentifier forIndexPath:indexPath];

    if(!cell)
    
        cell = [[[NSBundle mainBundle] loadNibNamed:@"CustomCell" 
                        owner:self options:nil] objectAtIndex:0];

        cell.delegate = self;
        [cell initialSetup]; //Other stuff
    
    else
        [cell resetCell];

    //And other awesome stuff

    return cell;

这“有效”。当我启动我的应用程序时,我自己的自定义单元格正在显示。 然而,事实证明该单元格从未从[self dequeue.. 返回为nil。因此,if 语句if(!cell) 永远不会为真。我在这个语句中有额外的设置,我想执行,但我不知道现在第一次初始化单元格的位置。如果我删除registerNib,那么这个陈述是正确的,但是对于所有单元格都是正确的,并且不会被出列。

我可能可以解决这个问题,并将我的initialSetup(和其他东西)放在 CustomCell 类的-(id)initWithCoder..-方法中,但我想知道我的单元格现在在哪里被初始化。为什么我的单元格在cellForRowAtIndexPath 之前存在?

【问题讨论】:

你在使用storyboard吗? 那么if(!cell) 将不成立,因为dequeueReusableCellWithIdentifier 返回一个单元格。在CustomCell中使用awakeFromNib方法 @Akhilrajtr 但dequeue.. 的意义不在于我在重复使用自己的细胞吗?我想象的方式是,在发布时 - 没有单元格已排队。我从来没有做过,所以他们怎么会排队,对吧?然后,当我向下滚动 10 行时,我创建的第一个单元格将被排队而不是被释放,以便我以后可以使用它。当我需要第 11 个单元格时,它首先通过调用dequeueReusable.. 来检查这个队列。由于我的第一个单元格已排队,因此将在此处返回。这对我来说很有意义。如果你们说dequeue总是返回一个单元格,那我什么都不懂。 我看到的所有例子都把if(!cell)放在dequeueReusableCell..之后。另外,使用awakeFromNib 而不是-initWithCoder 对我来说有什么区别? 覆盖prepareForReuseUITableViewCell 方法 【参考方案1】:

当您使用方法registerClass:forCellReuseIdentifierregisterNib:forCellReuseIdentifier在表格视图中注册一个类或nib时,如果您调用dequeueReusableCellWithIdentifier:时没有可用的单元格,则表格视图内部将创建一个单元格的实例,因此初始化代码是委托内部不再需要。

来自UITableView.h 代码:

// Beginning in ios 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

根据使用的register 方法,调用的init 方法有:

initWithStyle:reuseIdentifier 用于使用 registerClass: 注册的单元格 initWithCoder: 用于使用 registerNib: 注册的单元格

如果您使用registerNib:,您也可以在单元格中使用awakeFromNib 方法,这也是放置单元格初始化代码的好地方。使用initWithCoder:awakeFromNib 的主要区别在this question 中进行了说明。

当一个单元格被重用时,您可以在单元格中使用prepareForReuse 方法对单元格进行一些清理,并使其准备好再次配置。

处理所有这些的好方法是:

//ViewController code

- (void)viewDidLoad

    ...
    [_tableView registerNib:[UINib nibWithNibName:@"CellSample" bundle:Nil] forCellReuseIdentifier:@"cellIdentifier"];
    ...


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

   UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"];
   //configure the new cell, no if (!cell) needed
   return cell;



//Cell code

- (id)initWithCoder:(NSCoder *)aDecoder

    self = [super initWithCoder:aDecoder];
    if (self) 
        //You can put initialization here
    
    return self;



- (void)awakeFromNib

    [super awakeFromNib];
    //But is better initialize here



- (void)prepareForReuse

    //Reuse and reset the cell here

希望对你有帮助

【讨论】:

【参考方案2】:

使用dequeueReusableCellWithIdentifier: forIndexPath: 时,您不必像使用默认UITableViewCell 那样分配单元格。在您的自定义 UITableViewCell 子类中,它在初始化时被调用:

- (void)awakeFromNib 
     [super awakeFromNib];

所以把它加进去,你应该会很好。

【讨论】:

【参考方案3】:
- (instancetype)initWithStyle:(UITableViewCellStyle)style
              reuseIdentifier:(NSString *)reuseIdentifier
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
    //custom your cell
    
    return self;
  

【讨论】:

除了代码之外,通常最好提供一些关于原因或如何回答问题的解释。

以上是关于UITableViewCell 的初始化在哪里?的主要内容,如果未能解决你的问题,请参考以下文章

无法与 UITableViewCell 中的任何内容进行交互,我在某处被布尔值阻塞,它在哪里?

在哪里编写方法drawRect:iPhone SDK中的UIViewController和UITableViewCell

Xcode interface Builder 没有给我选择在哪里放置 UITableViewCell 的重用标识符

如何在 UITableViewCell 上使用自定义初始化程序?

在 UITableviewcell headerview 的 UIView 中添加动态图像

为啥 UITableViewCell 初始化在 initWithCoder 中不起作用