需要帮助了解自定义uitableviewcell初始化

时间:2014-03-20 15:35:34

标签: ios objective-c uitableview

UITableViewCell中实施自定义tableView:cellForRowAtIndexPath:时,这两种方式之间存在差异

loadNibNamed:owner:options:

SimpleTableCell *cell = [[SimpleTableCell alloc]init];

loadNibNamed:owner:options:也是alloc init吗?如果没有SimpleTableCellalloc init将如何运作?

SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil) 
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"SimpleTableCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

没有显式调用SimpleTableCell *cell = [[SimpleTableCell alloc]init];

2 个答案:

答案 0 :(得分:2)

好的,首先关闭。我根本不会回答这个问题。相反,我将告诉您如何创建和使用自定义UITableViewCell子类。你现在正在做的事情是对的。

让我们坚持您使用的名称SimpleTableCell

创建子类

创建UITableViewCell

的子类

SimpleTableCell.h

@interface SimpleTableCell : UITableViewCell

// if coding only
@property (nonatomic, strong) UILabel *simpleLabel

// if from nib
@property (nonatomic, weak) IBOutlet UILabel *simpleLabel;

@end

SimpleTableCell.m

#import "SimpleTableCell.h"

@implementation SimpleTableCell

// if coding only
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        //create the simpleLabel and add to self.contentView
    }
    return self;
}

// if from nib no need to do anything at all

// other stuff...

- (void)prepareForReuse
{
    // empty the cell here.
    // means you don't have to empty everything out in the controller
    self.simpleLabel.text = @"";
}

@end

好的,现在我们有一个细胞类。

创建NIB,如果这是您想要的

看起来你已经这样做了。

创建具有相同名称的笔尖(或不是,并不重要)。

将顶级项目设为UITableViewCell并将子类设置为SimpleTableCell。现在连接插座。在此示例中,simpleLabel就是要连接的所有内容。

使用表格视图注册子类

在拥有表视图的视图控制器中。这意味着表格视图可以处理单元格的创建和出列,您根本不必手动创建它们。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // set up the other stuff...

    // if coding only
    [self.tableView registerClass:[SimpleTableCell class] forCellReuseIdentifier:@"SimpleCell"];

    // if from a nib
    UINib *cellNib = [UINib nibWithNibName:@"SimpleTableCell" bundle:[NSBundle mainBundle]];
    [self.tableView registerNib:cellNib forCellReuseIdentifier:@"SimpleCell"];
}

现在,您只需让表格处理创建单元格。它跟踪重用标识符和单元队列,以便它可以正常处理所有内容。您只需要让它使用您为其注册子类的标识符为您出列单元格。

- (UITableViewCell*)tableView:(UITableView *)tableView cellFroRowAtIndexPath:(NSIndexPath *)indexPath
{
    // This API was introduced in iOS6 and will ALWAYS return a valid cell.
    // However, you need to register the class or nib with the table first.
    // This is what we did in viewDidLoad.
    // If you use a storyboard or nib to create a tableview and cell then this works too.
    SimpleTableCell *mySimpleCell = [tableView dequeueReusableCellWithIdentifier:@"SimpleCell" forIndexPath:indexPath];

    mySimpleCell.simpleLabel.text = @"Hello, World";

    return mySimpleCell;
}

修改

您可以使用...

创建一个单元格(实际上是任何类)
SimpleTableCell *cell = [[SimpleTableCell alloc] init];

但这样做意味着它没有与表视图或队列的一部分相关联。

从我的答案中的方法向下一步(如果你愿意)是使用旧的dequeuReusableCell...方法,然后检查它是否为零,并按照这样创建它......

- (UITableViewCell*)tableView:(UITableView *)tableView cellFroRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Old way, don't do this if you're targeting iOS6.0+
    SimpleTableCell *mySimpleCell = [tableView dequeueReusableCellWithIdentifier:@"SimpleCell"];

    if (!mySimpleCell) {
        // have to use initWithStyle:reuseIdentifier: for the tableView to be able to dequeue
        mySimpleCell = [[SimpleTableCell alloc] initWithStyle:UITableViewCellStyleCustom reuseIdentifier:@"SimpleCell"];
    }

    mySimpleCell.simpleLabel.text = @"Hello, World";

    return mySimpleCell;
}

我甚至不确定你是否可以从这里的笔尖加载,因为你无法在单元格上设置重用标识符。

多个细胞亚类

好的,上次编辑:D

对于多个UITableViewCell子类,您也可以使用它。我过去做过这个。例如,您可能有一个Post项的单元格,Image项目的单元格,Comment项目的单元格等等......它们都是不同的。

因此...

- (void)viewDidLoad
{
    // the rest

    // register each subclass with a different identifier
    [self.tableView registerClass:[PostCell class] forCellReuseIdentifier:@"PostCell"];
    [self.tableView registerClass:[ImageCell class] forCellReuseIdentifier:@"ImageCell"];
    [self.tableView registerClass:[CommentCell class] forCellReuseIdentifier:@"CommentCell"];
}

为了帮助保持这个小(并且它对NSFetchedResultsControllers也很方便,我将单元格的配置移到另一个方法。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;

    if (the required cell is a post cell) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"PostCell" forIndexPath:indexPath];
        [self configurePostCell:(PostCell *)cell atIndexPath:indexPath];
    } else if (the required cell is a image cell) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"ImageCell" forIndexPath:indexPath];
        [self configureImageCell:(ImageCell *)cell atIndexPath:indexPath];
    } else if (the required cell is a comment cell) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"CommentCell" forIndexPath:indexPath];
        [self configureCommentCell:(CommentCell *)cell atIndexPath:indexPath];
    }

    return cell;
}

- (void)configurePostCell:(PostCell *)postCell atIndexPath:(NSIndexPath *)indexPath
{
    // get the object to be displayed...

    postCell.postLabel = @"This is the post text";
    postCell.dateLabel = @"5 minutes ago";
}

- (void)configureImageCell:(ImageCell *)imageCell atIndexPath:(NSIndexPath *)indexPath
{
    // get the object to be displayed...

    imageCell.theImageView.image = //the image
    imageCell.dateLabel = @"5 minutes ago";
}

- (void)configureCommentCell:(CommentCell *)commentCell atIndexPath:(NSIndexPath *)indexPath
{
    // you get the picture...
}

答案 1 :(得分:0)

loadNibNmed:...要求系统从nib文件中的固定实例重新创建一个对象(通常但不限于UIView)。使用Xcode的界面构建器部分创建nib文件。

当从nib文件加载对象时loadNibNamed...init没有被调用,而是调用initWithCoder:。如果您要在从nib文件加载的视图上进行后初始化设置,通常的方法是awakeFromNib并调用[super awakeFromNib]