89

我能够设计自定义 UITableViewCells 并使用http://forums.macrumors.com/showthread.php?t=545061中的线程中描述的技术很好地加载它们。但是,使用该方法不再允许您使用重用标识符初始化单元格,这意味着您必须在每次调用时创建每个单元格的全新实例。有没有人想出一个好方法来缓存特定的单元格类型以供重用,但仍然能够在 Interface Builder 中设计它们?

4

16 回答 16

119

实际上,由于您是在 Interface Builder 中构建单元格,因此只需在此处设置重用标识符:

IB_reuse_identifier

或者,如果您正在运行 Xcode 4,请检查属性检查器选项卡:

在此处输入图像描述

(编辑:你的 XIB 由 XCode 生成后,它包含一个空的 UIView,但我们需要一个 UITableViewCell;所以你必须手动删除 UIView 并插入一个 Table View Cell。当然,IB 不会显示任何 UITableViewCell 参数界面视图。)

于 2009-04-18T23:08:45.933 回答
74

只需使用适当的方法签名实现一个方法:

- (NSString *) reuseIdentifier {
  return @"myIdentifier";
}
于 2009-01-05T18:21:49.780 回答
66

现在,在 iOS 5 中有一个合适的 UITableView 方法:

- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
于 2012-04-10T11:45:52.383 回答
47

我不记得我最初是在哪里找到这段代码的,但到目前为止它对我来说一直很好。

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

    static NSString *CellIdentifier = @"CustomTableCell";
    static NSString *CellNib = @"CustomTableCellView";

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
        cell = (UITableViewCell *)[nib objectAtIndex:0];
    }

    // perform additional custom work...

    return cell;
}

示例界面生成器设置...

替代文字

于 2009-07-19T02:05:27.033 回答
12

看看我对这个问题的回答:

是否可以在 Interface Builder 中设计 NSCell 子类?

在 IB 中设计 UITableViewCell 不仅是可能的,而且是可取的,因为否则所有手动连接和放置多个元素都非常繁琐。只要您尽可能小心地使所有元素不透明,性能就很好。在 IB 中为 UITableViewCell 的属性设置了重用 ID,然后在尝试出队时在代码中使用匹配的重用 ID。

去年,我还从 WWDC 的一些演讲者那里听说,您不应该在 IB 中制作表格视图单元格,但这是一大堆废话。

于 2009-01-05T20:42:28.233 回答
7

从 iOS 大约 4.0 开始,iOS 文档中有特定说明可以使这项工作超快:

http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7

向下滚动到它谈论子类化 UITableViewCell 的地方。

于 2011-01-17T21:31:21.210 回答
6

这是另一种选择:

NSString * cellId = @"reuseCell";  
//...
NSArray * nibObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:nil options:nil];

for (id obj in nibObjects)
{
    if ([obj isKindOfClass:[CustomTableCell class]])
    {
        cell = obj;
        [cell setValue:cellId forKey:@"reuseIdentifier"];
        break;
    }
}
于 2011-12-09T00:47:08.933 回答
2

路易斯方法对我有用。这是我用来从笔尖创建 UITableViewCell 的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"CustomCellId"];

    if (cell == nil) 
    {
        UIViewController *c = [[UIViewController alloc] initWithNibName:@"CustomCell" bundle:nil];
        cell = (PostCell *)c.view;
        [c release];
    }

    return cell;
}
于 2009-02-10T12:51:23.760 回答
2

我以类似的方式创建自定义视图单元 - 除了我通过 IBOutlet 连接单元。

[nib objectAt...]方法容易受到数组中项目位置的变化的影响。

这种UIViewController方法很好——刚刚尝试过,效果很好。

但...

在所有情况下initWithStyle都不会调用构造函数,因此不会进行默认初始化。

我已经阅读了有关使用initWithCoderor的各种地方awakeFromNib,但没有确凿的证据表明其中任何一个都是正确的方法。

除了在方法中显式调用一些初始化方法外,cellForRowAtIndexPath我还没有找到答案。

于 2010-01-22T11:31:42.900 回答
2

不久前,我在blog.atebits.com上发现了一篇关于此主题的精彩博文,并从那时起开始使用 Loren Brichter ABTableViewCell 类来完成我所有的 UITableViewCells。

您最终会得到一个简单的容器 UIView 来放置所有小部件,并且滚动速度非常快。

希望这是有用的。

于 2010-05-27T00:18:53.393 回答
2

这种技术也有效,并且不需要在视图控制器中使用时髦的 ivar 来进行内存管理。在这里,自定义表格视图单元位于名为“CustomCell.xib”的 xib 中。

 static NSData *sLoadedCustomCell = nil;

 cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
 if (cell == nil) 
 {
   if (sLoadedCustomCell == nil) 
   {        
      // Load the custom table cell xib
      // and extract a reference to the cell object returned
      // and cache it in a static to avoid reloading the nib again.

      for (id loadedObject in [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil]) 
      {
        if ([loadedObject isKindOfClass:[UITableViewCell class]]) 
        {
          sLoadedCustomCell = [[NSKeyedArchiver archivedDataWithRootObject: loadedObject] retain];
          break;
        }
    }
    cell = (UITableViewCell *)[NSKeyedUnarchiver unarchiveObjectWithData: sLoadedCustomCell];
  }
于 2010-09-29T00:30:36.570 回答
2
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *simpleTableIdentifier = @"CustomCell";

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

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}         

return cell;
}
于 2014-03-01T05:29:41.337 回答
1

gustavogb 解决方案对我不起作用,我尝试的是:

ChainesController *c = [[ChainesController alloc] initWithNibName:@"ChainesController" bundle:nil];
[[NSBundle mainBundle] loadNibNamed:@"ChaineArticleCell" owner:c options:nil];
cell = [c.blogTableViewCell retain];
[c release];

它似乎工作。blogTableViewCell 是单元格的 IBOutlet,ChainesController 是文件的所有者。

于 2010-07-08T09:59:58.020 回答
1

从 UITableView 文档中关于dequeueWithReuseIdentifier:“标识要重用的单元格对象的字符串。默认情况下,可重用单元格的标识符是它的类名,但您可以将其更改为任意值。”

自己覆盖 -reuseIdentifer 是有风险的。如果您的单元格子类有两个子类,并在一个表格视图中使用这两个子类,会发生什么情况?如果他们将重用标识符调用发送到 super 您将出列错误类型的单元格........我认为您需要覆盖重用标识符方法,但让它返回一个被替换的标识符细绳。或者,如果没有指定,让它以字符串形式返回类。

于 2011-11-04T09:24:44.503 回答
0

对于它的价值,我在一次 iPhone 技术讲座上向一位 iPhone 工程师询问了这个问题。他的回答是,“是的,可以使用 IB 来创建单元格。但不要。拜托,不要。”

于 2009-01-05T20:27:41.447 回答
0

我按照 Ben Mosher 链接的 Apple 说明进行操作(谢谢!),但发现 Apple 忽略了一个重要点。他们在 IB 中设计的对象只是一个 UITableViewCell,他们从中加载的变量也是如此。但如果你真的将它设置为 UITableViewCell 的自定义子类,并为子类编写代码文件,你可以在代码中编写 IBOutlet 声明和 IBAction 方法,并将它们连接到 IB 中的自定义元素。那么就不需要使用视图标签来访问这些元素,你可以创建任何你想要的疯狂单元格。这是可可触摸的天堂。

于 2011-08-22T21:02:50.733 回答