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

我创建了自己的CustomTableView 和CustomCell。单元格在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 对我来说有什么区别?
  • 覆盖prepareForReuse 的UITableViewCell 方法

标签: ios objective-c uitableview xib


【解决方案1】:

当您使用方法registerClass:forCellReuseIdentifier或registerNib: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;
        }
      

      【讨论】:

      • 除了代码之外,通常最好提供一些关于原因或如何回答问题的解释。
      猜你喜欢
      • 2014-04-27
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 1970-01-01
      • 2021-06-25
      • 2016-08-16
      • 1970-01-01
      相关资源
      最近更新 更多