小编典典

如何从 Xib 文件中加载自定义 UITableViewCells?

all

问题很简单:如何UITableViewCell从 Xib 文件加载自定义?这样做允许您使用 Interface Builder
来设计您的单元格。由于内存管理问题,答案显然并不简单。该线程提到了该问题并提出了解决方案,但它是 NDA
发布之前的版本并且缺少代码。这是一个很长的帖子,讨论了这个问题,但没有提供明确的答案。

这是我使用过的一些代码:

static NSString *CellIdentifier = @"MyCellIdentifier";

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

要使用此代码,请创建 MyCell.m/.h,它是您想要的组件的新子类UITableViewCell并添加IBOutlets。然后创建一个新的“空
XIB”文件。在 IB 中打开 Xib
文件,添加一个UITableViewCell对象,将其标识符设置为“MyCellIdentifier”,并将其类设置为 MyCell
并添加您的组件。最后,连接IBOutlets到组件。请注意,我们没有在 IB 中设置文件的所有者。

其他方法提倡设置文件的所有者,如果 Xib 没有通过额外的工厂类加载,则会警告内存泄漏。我在 Instruments/Leaks
下测试了上述内容,没有发现内存泄漏。

那么从 Xibs
加载单元的规范方法是什么?我们设置文件的所有者吗?我们需要工厂吗?如果是这样,工厂的代码是什么样的?如果有多种解决方案,让我们澄清每个解决方案的优缺点......


阅读 73

收藏
2022-04-21

共1个答案

小编典典

以下是原作者陈述的 IB 工程师推荐的两种方法。

有关更多详细信息,请参阅实际帖子。我更喜欢方法#2,因为它看起来更简单。

方法#1:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Create a temporary UIViewController to instantiate the custom cell.
        UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
        // Grab a pointer to the custom cell.
        cell = (BDCustomCell *)temporaryController.view;
        [[cell retain] autorelease];
        // Release the temporary UIViewController.
        [temporaryController release];
    }

    return cell;
}

方法#2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

更新(2014 年): 方法 #2
仍然有效,但不再有相关文档。它曾经在官方文档中,但现在被删除以支持故事板。

我在 Github 上发布了一个工作示例:
https
://github.com/bentford/NibTableCellExample

为 Swift 4.2 编辑

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.tblContacts.register(UINib(nibName: CellNames.ContactsCell, bundle: nil), forCellReuseIdentifier: MyIdentifier)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier, for: indexPath) as! ContactsCell

    return cell
}
2022-04-21