在情节提要中,如何制作自定义单元以与多个控制器一起使用? [英] In a storyboard, how do I make a custom cell for use with multiple controllers?

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

问题描述

我正在尝试在我正在开发的应用中使用故事板.在应用程序中有 ListsUsers 并且每个都包含其他的集合(列表的成员,用户拥有的列表).因此,相应地,我有 ListCellUserCell 类.目标是让它们在整个应用程序中可重用(即,在我的任何 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.

  • 在 Controller #1 中,添加了一个原型单元,将类设置为我的 UITableViewCell 子类,设置重用 id,添加标签并将它们连接到类的出口.在 Controller #2 中,添加了一个空的原型单元,将其设置为相同的类并像以前一样重用 id.当它运行时,当单元格显示在控制器 #2 中时,标签永远不会出现.在控制器 #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 中设计每种细胞类型,并连接到适当的细胞类别.在情节提要中,添加了一个空原型单元格并设置其类并重用 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,如果我杀死了原型单元,则为重用 id 注册我的 NIB 会起作用.但是,我将无法设置从单元格到其他帧的转场,这确实是使用情节提要的全部意义所在.

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. 根据该单元所在的场景,从该单元配置独特的故事板转场.

很遗憾,目前没有办法做到这一点.要了解为什么您以前的尝试不起作用,您需要更多地了解故事板和原型表视图单元格的工作原理.(如果您不关心为什么这些其他尝试不起作用,请随时离开.除了建议您提交错误之外,我没有任何神奇的解决方法.)

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 中定义的属性.(IBOutlets 也可能在这里连接,虽然我还没有测试过;它可能发生在 -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.什么时候它运行,当单元格显示时,标签永远不会出现控制器 #2.在控制器 #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.

    这是意料之中的.虽然两个单元具有相同的类,但传递给控制器​​#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 中设计每种细胞类型并连接到适当的细胞类别.在情节提要中,添加了一个空的原型单元格并设置它的类并重用 id 来引用我的单元类.在控制器的 viewDidLoad 方法,为重用标识.显示时,两个控制器中的单元格都是空的,就像原型.

    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.

    同样,这是意料之中的.重用标识符不在情节提要场景或 nib 之间共享,因此所有这些不同的单元格具有相同的重用标识符这一事实毫无意义.您从 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,然后您将返回同一个单元格.(这并不是因为原型覆盖"了 nib;您只是没有在 tableview 中注册 nib,所以它仍在查看嵌入在情节提要中的 nib.)不幸的是,这种方法有一个缺陷——没有办法将故事板转场连接到独立 nib 中的单元格.

    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天全站免登陆