如何将在IB中创建的自定义UITableViewCell类加载到UITableView中?

5

我是一个新手,请您多多包涵:

在IB中,我有一个包含UITableView的UIScrollView的.xib。 我想将自定义的UITableViewCells加载到UITableView中。 我已经在IB中创建了四五个自定义单元格,但无法正确加载第一个。

以下是IB中相关的屏幕截图:

.xib 定制单元格“itemCell”

我已将在IB中创建的自定义UITableViewCell的类设置为我创建的UITableView类的“itemCell”。此外,我还将三个文本字段的输出和代理连接到“itemCell”。

这是itemCell.h:

#import <UIKit/UIKit.h>

@interface itemCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UITextField *quantityTextField;
@property (weak, nonatomic) IBOutlet UITextField *itemTextField;
@property (weak, nonatomic) IBOutlet UITextField *priceTextField;

@end

这里是itemCell.m文件:

#import "itemCell.h"

@implementation itemCell
@synthesize quantityTextField,itemTextField,priceTextField;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code

    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

在filecontroller.m中,这是rootcontroller .xib的实现文件,当用户按下按钮时,我会基于此创建一个新的单元格(将其添加到数组中),然后重新加载tableview。 我没有收到任何错误,但我得到了一个普通的单元格,而不是我在IB中创建的内容。 这里是rootcontroller.m。 非常感谢您的帮助。
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    scrollView =(UIScrollView *)self.view;
    items = [[NSMutableArray alloc] init];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [items count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        return [items objectAtIndex:[indexPath row]];
}

- (UITableViewCell *)initiateNewCell{
    itemCell *cell = [[itemCell alloc] init];
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.selectionStyle = UITableViewCellSelectionStyleBlue;
    return cell;
}

- (IBAction)addItem:(id)sender {
    //creates the new cell to be added
    [items addObject:[self initiateNewCell]];
    [self.tableView reloadData];

这些自定义单元格将被重用(多次显示)还是仅在您的UITableView中使用一次? 此外,UITableView建立在UIScrollView上,在您的情况下,我认为没有必要将UITableView放入UIScrollView中。 - Josh Bernfeld
这些自定义单元格将被多次显示。每当用户点击添加按钮时,理想情况下会创建一个新行并填充自定义单元格。我认为我的问题可能在IB中。我已经在视图控制器之外创建了一个UITableViewCell。它应该在视图控制器之上还是无关紧要的?感谢有关滚动视图的信息。 - IkegawaTaro
只是一个提醒,类名应该始终以大写字母开头,以遵循标准命名约定,因此它真的应该是“ItemCell”。但是,您可能还想考虑更具描述性的名称。 - Michael Mior
谢谢@MichaelMior,我以后会这样做的。 - IkegawaTaro
3个回答

8

从 iOS 5 开始,您现在可以使用以下函数从 nib 中加载 UITableViewCell 以进行单元格重用。

- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier

  1. First make sure you create an IB file that contains only the UITableViewCell
  2. Under Identify inspector: Set the class of the UITableViewCell to "itemCell" enter image description here
  3. Under attributes inspector: Set the identifier of the UITableViewCell to "itemCellIdentifier" enter image description here
  4. In viewDidLoad: place the following code, and replace itemCellNibName with the name of the nib that contains the UITableViewCell.

    NSString *myIdentifier = @"itemCellIdentifier";
    [self.tableView registerNib:[UINib nibWithNibName:@"itemCellNibName" bundle:nil] forCellReuseIdentifier:myIdentifier];
    
  5. In cellForRowAtIndexPath: place the following code, you can now access your IBOutlet properties you set on the itemCell, and connected in the nib.

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
    {
         static NSString *myIdentifier = @"itemCellIdentifier";
    
         itemCell *cell = (itemCell *)[tableView dequeueReusableCellWithIdentifier:myIdentifier];
         cell.textLabel.text = [NSString stringWithFormat:@"Test Row:%i!",indexPath.row];
         return cell;
    }
    

另外需要注意的是:不要将UITableView放置在UIScrollView中,因为UITableView已经内置了UIScrollView,这样可以实现正确的单元格排队。

此外,我建议您先将基本功能实现,然后再从数组中提取数据。

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
         return 10;
    }

另外:正如其他人所提到的,该数组包含将填充UITableViewCells的数据,而不是实际的单元格本身。

非常感谢你的回复。我有一个问题。对于第四步,我项目中唯一的“NIB”文件(我认为)就是ViewController.xib。在其中有一个UIViewController和我已经贴出作为图像的UITableViewCell。我应该使用哪个NIB文件名来替换@"itemCellNibName" @"ViewController"?根据您的建议,我已经大大简化了代码以先掌握基础知识。 - IkegawaTaro
好的,你需要做的是将它们分别放入自己的nib文件中。让我们来创建一个UITableViewCell的nib文件。在菜单栏中,选择文件->新建->文件。在弹出的窗口中,在左侧列中选择用户界面。选择"空白"选项。设备类型选择iPhone。将其命名为itemCellNib。 在这个新的nib文件中,拖入一个UITableViewCell,并按照上面的说明进行操作。 在ViewController的nib文件中,将UITableViewCell删除。 所以对于NIB文件名,你将输入@"itemCellNib"。 - Josh Bernfeld
谢谢!在过去的30分钟里,我找到了另一个网站,讲述了如何创建单独的nib文件 - 我已经这样做了,并且成功地让我的代码工作了。你真是太棒了,让这一天漫长而令人沮丧的日子变成了充满回报的夜晚。 - IkegawaTaro
在第5步:您需要调用if(cell == nil) { cell = [itemCell new]; } 否则,如果没有单元格可重用,则不会创建新单元格。这应该在尝试重用单元格的行之后完成。除此之外,答案很棒。 - Groot
@Filip - 其实不是这样,苹果文档中关于该方法的说明是:“在出列任何单元格之前,请调用此方法或registerClass:forCellReuseIdentifier:方法告诉表视图如何创建新的单元格。如果指定类型的单元格当前不在重用队列中,则表视图使用提供的信息自动创建一个新的单元格对象。” - Levi
1
这里有一个非常好的教程,教你如何操作:briterideas.blogspot - IkegawaTaro

3
在你的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    //This identifier string needs to be set in cell of the TableViewController in the storyboard
    static NSString *CellIdentifier = @"Cell";

    // Resuse the cell
    SomeCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // If there are no cell to be reused we create a new one
    if(cell == nil) {
        cell = [SomeCustomCell new];
    }

    // Configure the cell...
    NSString *someString = [yourArrayWithStringsOrWhatEver objectAtIndex:indexPath.row];

    // Setting the some property of your custom cell
   [cell.yourSpecificCellProperty someString];

   [cell.yourOtherSpecificCellProperty setText:@"What Ever your want!"];
}

你的单元格属性可以是你在界面构建器中连接到自定义单元格的任何内容。

希望这有所帮助!


1

有几个问题需要解决:

  • 类名以大写字母 itemCell 开头 -> ItemCell
  • 应该重用单元格。按照你的方式,将为每个索引路径创建一个单独的单元格。
  • items 数组应仅包含您表格的数据源,而不是单元格。
  • 可以向表格添加一行,而不是调用重新加载数据,这也可以进行动画处理。

尝试像这样:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    scrollView =(UIScrollView *)self.view;
    items = [[NSMutableArray alloc] init];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [items count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [[NSBundle mainBundle] loadNibNamed:@"itemCell" owner:self options:nil].lastObject;
        cell.reuseIdentifier = CellIdentifier;
    }

    // Do any additional setup to the cell

    return cell;
}

- (IBAction)addItem:(id)sender {
    [items addObject:[NSNumber numberWithInt:items.count]]; // Here comes the data source
    [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}

附注:我没有使用IDE编写,所以可能会有一些错误。


非常感谢您的回复。剩下的问题是:1)'cell.reuseIdentifier = CellIdentifier;' 给我报错:"assignment to readonly property"。2)当点击“add”时,我收到另一个关于“invalid number of rows”的错误。似乎结果行数仍为0,而应该是1。有什么想法吗?此外 - 我对这一行感到困惑:cell = [[NSBundle mainBundle] loadNibNamed:@"itemCell" owner:self options:nil].lastObject; 在IB中的单个UITableViewCell是否被认为是nib? - IkegawaTaro
你不能使用 cell.reuseIdentifier = CellIdentifier。相反,应该在 itemCell NIB 中设置重用标识符。 - Michael Mior
关于重复使用ID的问题,迈克尔是正确的,应该从nib文件中设置它。至于错误,如果没有运行您的代码,我不知道出了什么问题。而nib是一个带有XIB扩展名的文件,您应该为您的“itemCell”创建一个单独的nib文件。 - Levi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接