使用 UINib 为 UITableViewCell 分配插座

Posted

技术标签:

【中文标题】使用 UINib 为 UITableViewCell 分配插座【英文标题】:Assigning the outlet for a UITableViewCell using UINib 【发布时间】:2012-02-02 00:54:23 【问题描述】:

我查看了 Apple 的 WWDC 2010 代码中的 TableViewUpdates/TVAnimationGestures,但在复制 UITableViewCell 子类时遇到了麻烦。这就是我所做的:

我用一些简单的属性创建了一个新的 UITableViewCell 子类:

@interface TargetDetailTableViewCell : UITableViewCell

@property (nonatomic, retain) IBOutlet UILabel *DescriptionLabel;
@property (nonatomic, retain) IBOutlet UILabel *ValueLabel;
@property (nonatomic, retain) IBOutlet UIImageView *DotImageView;

在.m中,我只是释放内存。在 IB 中,我将我刚刚拖入 IB 的 UITableViewCell 的类更改为 TargetDetailTableViewCell。我将 TargetDetailTableViewCell 的出口连接到适当的标签和图像视图。

在课堂上我想用这个:

@class TargetDetailTableViewCell;

//some properties
@property (nonatomic, assign) IBOutlet TargetDetailTableViewCell *TargetCell;

在.m中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath     
    static NSString *TargetCellIdentifier = @"TargetDetailTableViewCellIdentifier";
    TargetDetailTableViewCell *cell = (TargetDetailTableViewCell *)[tableView dequeueReusableCellWithIdentifier:TargetCellIdentifier];

    if (cell == nil) 
        UINib *nib = [UINib nibWithNibName:@"TargetDetailTableViewCell" bundle:nil];
        [nib instantiateWithOwner:self options:nil];
        cell = self.TargetCell;
        self.TargetCell = nil;
    
// set some labels
return cell;

当我运行它时,我得到了错误:Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

我认为 Apple 的示例与我的示例之间唯一不同的是,当我在他们的 IB 中 ctlr-单击 UITableViewCell 的子类时,他们设置了一个 File's Owner 属性。我不知道他们是如何连接那个插座的,因为它在他们使用单元的类中被声明为一个属性,但是他们没有建立物理 IB 连接。有人可以向我解释一下或者我做错了什么吗?

另外,如果有人能解释一下,那就太好了:

        UINib *nib = [UINib nibWithNibName:@"TargetDetailTableViewCell" bundle:nil];
        [nib instantiateWithOwner:self options:nil];
        cell = self.TargetCell;
        self.TargetCell = nil;

似乎您创建了笔尖,而从内存中实例化的笔尖的所有者是您所在的类或自己(我的视图控制器)。然后最后两行让我感到困惑。这就像你告诉你的单元格指向新创建的对象,然后你将新创建的对象设置为 nil。我认为在我的脑海中,单元格现在也指向零。谢谢。

【问题讨论】:

【参考方案1】:

您需要在您的自定义表格视图单元格 nib 中有一个所有者,并且该所有者需要是您的 TableViewDataSource 类(即实现 cellForRowAtIndexPath 方法并具有到表格单元格的 TargetCell 出口的表格视图控制器)。

您还需要将来自文件所有者(TableViewController)的 TargetCell 出口连接到您的自定义表格视图。

这样做的原因是,当您加载 nib 时,以您的表格视图控制器为所有者,它将设置您拥有的插座(TargetCell 属性)指向您笔尖中定义的表格视图单元格。

然后将此引用复制到单元格方法变量,对其进行配置并返回它。在复制它之后将属性分配给 nil,因为您只需要它作为引导程序来获取对 nib 中对象的引用,以便在 cellForRowAtIndexPath 方法中使用。

【讨论】:

快速跟进问题。所以cell = self.TargetCell 复制该对象,不只是指向将在下一行使其为零的引用吗?如果我想重用这个自定义 UITableViewCell,我是否将另一个 File's Owner 对象添加到我的 nib 并做同样的事情?再次感谢。 self.TargetCell 是对 UITableViewCell 对象实例的引用。您将此引用复制到本地“单元格”变量,因此由于此第二个引用,该对象将保留到方法结束。然后在方法结束时返回单元格,表格视图现在有对它的引用,因此它被表格视图保留。当您设置 self.TargetCell = nil 时,您只是在清除对该对象的特定引用(即您没有执行 [self.TargetCell release]),这也会释放底层对象。这只是您要清除的参考。 要在不同的表格视图控制器中重用相同的自定义表格单元格和笔尖,您可能需要定义一个通用的“MyCellOwner”对象,该对象具有此表格单元格类型的出口并将其设置为所有者在表格单元笔尖而不是表格视图控制器中。然后在 cellForRowAtIndex 代码中分配/初始化一个“MyCellOwner”并使用它来加载 nib(即作为调用中的所有者字段),这将在 MyCellOwner 对象的该实例中创建对表格单元格的引用。然后从该引用中复制。 (可能有一种更简单的方法,我可能会使它过于复杂。)

以上是关于使用 UINib 为 UITableViewCell 分配插座的主要内容,如果未能解决你的问题,请参考以下文章

生成自定义 UIView 的 UINib 实例给出“不符合键值编码”错误

Objective-C - 给定一个 UINib 实例,我如何初始化我的自定义 UIView?

在 UITableView 中的 UINib 中重新加载 UITableView

UINib (iOS):可以从一个 nib 文件中实例化多个视图吗?

在我告诉他启动之前,不应启动 UINib 文件

UINib initWithNibName 在应用程序加载之前崩溃