在故事板中,如何制作用于多个控制器的自定义单元? [英] In a storyboard, how do I make a custom cell for use with multiple controllers?

查看:94
本文介绍了在故事板中,如何制作用于多个控制器的自定义单元?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我正在使用的应用中使用故事板。在应用程序中有列表用户,每个都包含其他列表(列表成员,用户拥有的列表)。因此,我有 ListCell UserCell 类。目标是让它们在整个应用程序中可重复使用(即,在我的任何tableview控制器中)。

I'm trying to use storyboards in an app I'm working on. In the app there are Lists and Users and each contains a collection of the other (members of a list, lists owned by a user). So, accordingly, I have ListCell and UserCell classes. The goal is to have those be re-usable throughout the app (ie, in any of my tableview controllers).

这就是我遇到问题的地方。

That's where I'm running into a problem.

如何在故事板中创建可在任何视图控制器中重复使用的自定义tableview单元格?

以下是我到目前为止所尝试的具体事项。

Here are the specific things I've tried so far.


  • 在控制器#1中,添加了一个原型单元格,将类设置为我的 UITableViewCell 子类,设置重用ID,添加标签并将它们连接到类的出口。在Controller#2中,添加了一个空的原型单元格,将其设置为同一个类并重复使用id。运行时,控制器#2中显示单元格时,标签永远不会出现。在Controller#1中正常工作。

  • In Controller #1, added a prototype cell, set the class to my UITableViewCell subclass, set the reuse id, added the labels and wired them to the class's outlets. In Controller #2, added an empty prototype cell, set it to the same class and reuse id as before. When it runs, the labels never appear when the cells are shown in Controller #2. Works fine in Controller #1.

在不同的NIB中设计每个单元格类型并连接到适当的单元类。在storyboard中,添加了一个空的原型单元格并设置其类并重用id来引用我的单元类。在控制器的 viewDidLoad 方法中,为重用ID注册了这些NIB文件。如图所示,两个控制器中的单元格都像原型一样是空的。

Designed each cell type in a different NIB and wired up to the appropriate cell class. In storyboard, added an empty prototype cell and set its class and reuse id to refer to my cell class. In controllers' viewDidLoad methods, registered those NIB files for the reuse id. When shown, cells in both controllers were empty like the prototype.

将两个控制器中的原型保持为空并设置类并将id重用到我的单元类。完全用代码构建单元格的UI。单元格在所有控制器中都能正常工作。

Kept prototypes in both controllers empty and set class and reuse id to my cell class. Constructed the cells' UI entirely in code. Cells work perfectly in all controllers.

在第二种情况下,我怀疑原型总是覆盖NIB,如果我杀死了原型单元,注册我的NIB以便重用id可以工作。但后来我无法设置从单元格到其他框架的segue,这实际上是使用故事板的全部要点。

In the second case I suspect that the prototype is always overriding the NIB and if I killed the prototype cells, registering my NIB for the reuse id would work. But then I wouldn't be able to setup segues from the cells to other frames, which is really the whole point of using storyboards.

在一天结束时,我想要两件事:在故事板中连接基于tableview的流,并在视觉上而不是在代码中定义单元格布局。到目前为止,我无法看到如何获得这两个。

At the end of the day, I want two things: wire up tableview based flows in the storyboard and define cell layouts visually rather than in code. I can't see how to get both of those so far.

推荐答案

据我所知,你想:


  1. 在IB中设计一个可用于多个故事板场景的单元格。

  2. 配置独特的故事板segues该单元格取决于单元格所在的场景。

不幸的是,目前无法做到这一点。要了解您之前的尝试无效的原因,您需要了解有关故事板和原型表视图单元格如何工作的更多信息。 (如果你不关心为什么这些其他尝试都不起作用,请随时离开。除了建议你提交错误之外,我没有为你提供任何神奇的解决方法。)

Unfortunately, there is currently no way to do this. To understand why your previous attempts didn't work, you need to understand more about how storyboards and prototype table view cells work. (If you don't care about why these other attempts didn't work, feel free to leave now. I've got no magical workarounds for you, other than suggesting that you file a bug.)

故事板本质上只不过是.xib文件的集合。当您从故事板中加载一个具有一些原型单元格的表视图控制器时,会发生以下情况:

A storyboard is, in essence, not much more than a collection of .xib files. When you load up a table view controller that has some prototype cells out of a storyboard, here's what happens:


  • 每个原型单元实际上是它的自己的嵌入式迷你笔尖。所以当表视图控制器加载时,它会遍历每个原型单元的nib并调用 - [UITableView registerNib:forCellReuseIdentifier:]

  • 表视图向控制器询问单元格。

  • 您可能调用 - [UITableView dequeueReusableCellWithIdentifier:]

  • 当您请求具有给定重用标识符的单元格时,它会检查是否已注册了nib。如果是,则实例化该单元的实例。这包括以下步骤:

  • Each prototype cell is actually its own embedded mini-nib. So when the table view controller is loading up, it runs through each of the prototype cell's nibs and calls -[UITableView registerNib:forCellReuseIdentifier:].
  • The table view asks the controller for the cells.
  • You probably call -[UITableView dequeueReusableCellWithIdentifier:]
  • When you request a cell with a given reuse identifier, it checks whether it has a nib registered. If it does, it instantiates an instance of that cell. This is composed of the following steps:


  1. 查看单元格的类,如单元格的nib中所定义。调用 [[CellClass alloc] initWithCoder:]

  2. -initWithCoder:方法遍历并添加子视图并设置在nib中定义的属性。 ( IBOutlet 也可能会在这里连接,虽然我没有测试过;它可能发生在 -awakeFromNib

  1. Look at the class of the cell, as defined in the cell's nib. Call [[CellClass alloc] initWithCoder:].
  2. The -initWithCoder: method goes through and adds subviews and sets properties that were defined in the nib. (IBOutlets probably get hooked up here as well, though I haven't tested that; it may happen in -awakeFromNib)


  • 您可以根据需要配置您的单元格。

  • You configure your cell however you want.

    这里需要注意的重要一点是,单元格的视觉外观之间有区别。细胞。您可以创建同一类的两个单独的原型单元格,但它们的子视图完全不同。实际上,如果你使用默认的 UITableViewCell 样式,这正是正在发生的事情。例如,默认样式和字幕样式都由相同的 UITableViewCell 类表示。

    The important thing to note here is there is a distinction between the class of the cell and the visual appearance of the cell. You could create two separate prototype cells of the same class, but with their subviews laid out completely differently. In fact, if you use the default UITableViewCell styles, this is exactly what's happening. The "Default" style and the "Subtitle" style, for example, are both represented by the same UITableViewCell class.

    这很重要:单元格的与特定的视图层次结构没有一对一的关联。某些视图层次结构完全取决于在此特定控制器中注册的原型单元格中的内容。

    This is important: The class of the cell does not have a one-to-one correlation with a particular view hierarchy. The view hierarchy is determined entirely by what's in the prototype cell that was registered with this particular controller.

    另请注意,单元格的重用标识符未在某些注册表中注册全球细胞药房。重用标识符仅在单个 UITableView 实例的上下文中使用。

    Note, as well, that the cell's reuse identifier was not registered in some global cell dispensary. The reuse identifier is only used within the context of a single UITableView instance.

    鉴于此信息,让我们看一下上述尝试中发生的情况。

    Given this information, let's look at what happened in your above attempts.


    在Controller#1中,添加了原型单元格,将类设置为我的
    UITableViewCell子类,设置重用ID,添加标签并将
    连接到类的出口。在Controller#2中,添加了一个空的
    原型单元格,将其设置为同一个类并重复使用id。当
    运行时,当
    Controller#2中显示单元格时,标签永远不会出现。在Controller#1中正常工作。

    In Controller #1, added a prototype cell, set the class to my UITableViewCell subclass, set the reuse id, added the labels and wired them to the class's outlets. In Controller #2, added an empty prototype cell, set it to the same class and reuse id as before. When it runs, the labels never appear when the cells are shown in Controller #2. Works fine in Controller #1.

    这是预期的。虽然两个单元格具有相同的类,但传递给Controller#2中的单元格的视图层次结构完全没有子视图。所以你得到一个空单元格,这正是你在原型中放入的单元格。

    This is expected. While both cells had the same class, the view hierarchy that was passed to the cell in Controller #2 was entirely devoid of subviews. So you got an empty cell, which is exactly what you put in the prototype.


    在不同的NIB中设计每个单元格类型并连线到
    适当的细胞类。在storyboard中,添加了一个空原型单元
    并设置其类并重用id来引用我的单元类。在
    controllers的viewDidLoad方法中,为
    重用id注册了那些NIB文件。如图所示,两个控制器中的单元格都是空的,就像
    原型一样。

    Designed each cell type in a different NIB and wired up to the appropriate cell class. In storyboard, added an empty prototype cell and set its class and reuse id to refer to my cell class. In controllers' viewDidLoad methods, registered those NIB files for the reuse id. When shown, cells in both controllers were empty like the prototype.

    同样,这是预期的。故障板场景或笔尖之间不共享重用标识符,因此所有这些不同的单元具有相同的重用标识符的事实是没有意义的。从tableview返回的单元格将具有与故事板场景中的原型单元格匹配的外观。

    Again, this is expected. The reuse identifier is not shared between storyboard scenes or nibs, so the fact that all of these distinct cells had the same reuse identifier was meaningless. The cell you get back from the tableview will have an appearance that matches the prototype cell in that scene of the storyboard.

    但此解决方案很接近。如您所述,您可以通过编程方式调用 - [UITableView registerNib:forCellReuseIdentifier:] ,传递包含该单元格的 UINib ,你会回到同一个细胞。 (这不是因为原型是覆盖笔尖;你只是没有用tableview注册笔尖,所以它仍然在看故事板中嵌入的笔尖。)不幸的是,这种方法有一个缺陷 - 没有办法将storyboard segue连接到独立笔尖中的单元格。

    This solution was close, though. As you noted, you could just programmatically call -[UITableView registerNib:forCellReuseIdentifier:], passing the UINib containing the cell, and you'd get back that same cell. (This isn't because the prototype was "overriding" the nib; you simply hadn't registered the nib with the tableview, so it was still looking at the nib embedded in the storyboard.) Unfortunately, there's a flaw with this approach — there's no way to hook up storyboard segues to a cell in a standalone nib.


    将两个控制器中的原型保持为空并设置类并重用id
    到我的手机课。完全用代码构建单元格的UI。单元
    在所有控制器中都能正常工作。

    Kept prototypes in both controllers empty and set class and reuse id to my cell class. Constructed the cells' UI entirely in code. Cells work perfectly in all controllers.

    自然。希望这不足为奇。

    Naturally. Hopefully, this is unsurprising.

    所以,这就是为什么它不起作用。您可以在独立的笔尖中设计单元格,并在多个故事板场景中使用它们;你现在无法将故事板细分与这些细胞联系起来。但是,希望你在阅读这篇文章的过程中学到了一些东西。

    So, that's why it didn't work. You can design your cells in standalone nibs and use them in multiple storyboard scenes; you just can't currently hook up storyboard segues to those cells. Hopefully, though, you've learned something in the process of reading this.

    这篇关于在故事板中,如何制作用于多个控制器的自定义单元?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆