如何在单个视图控制器中使用多个nib文件?

7

背景

我正在使用界面构建器为我正在开发的应用程序创建用户界面。该应用程序只有一个屏幕,显示一系列按钮。点击按钮会显示相关视图,该视图覆盖在按钮上方。点击另一个按钮会隐藏先前的覆盖视图并显示另一个视图。

为了在界面构建器中更轻松地管理UI,我决定为每个子视图创建多个nib文件,并在视图控制器的viewDidLoad方法中使用UINib类加载子视图的nib文件。

这样做的想法是避免在单个nib文件中堆叠多个视图,因为这在界面构建器中很难操作。我本可以在代码中创建所有视图,但由于每个子视图的布局都相当复杂(具有多个子视图),这将需要大量繁琐的编码。

以下是示例代码,用于从nib文件中加载子视图。

- (void)viewDidLoad
{
    UINib *aSubViewNib = [UINib nibWithNibName:@"aSubView" bundle:nil];
    NSArray *bundleObjects = [aSubViewNib instantiateWithOwner:self options:nil];

    // get root view from bundle array
    UIView *aSubView = [bundleObjects objectAtIndex:0];
    [self.view addSubview:aSubView];
...

上面的代码会在其他视图中重复使用。
简而言之,我有一个单屏 iPhone 应用程序,其中有分层视图,可以通过点击按钮显示/隐藏。这是通过单个视图控制器实现的,该视图控制器具有相关的 nib 文件和一系列附加的 nib 文件,用于在 view controller 的 viewDidLoad 方法中加载子视图。
问题:
抱歉介绍太长了,但我想非常清楚地表达我的做法。
1. 我的方法是否不好或不寻常? 2. 这样做有什么潜在的问题吗? 3. 当他们需要动态界面并且仍然想保持所有内容在界面构建器中时,其他人都做了什么?
注意:
在任何人问为什么我不只是在新屏幕上显示子视图并使用导航栏之前,让我说我有非常好的理由,并且我了解 iOS UI 指南。上面的用例并不完全是我的用例,但它清楚地描述了问题,而没有陷入我的开发应用程序。
此外,我知道我可以将所有子视图编写为代码,但每个子视图都有一个复杂的子视图布局,尝试使它们看起来正确会产生大量的代码和混乱。
提前感谢。
3个回答

1

视图控制器和视图之间并不一定存在1对1的关系。大多数视图包含许多子视图,这些子视图本身也是视图,因此这在字面上是没有意义的。

但是,根据视图(包括其内容)的复杂性,您可能需要单独的视图控制器...或者不需要。

例如,如果您有两个子视图,每个子视图都是tableViews,则可能需要为每个tableView创建一个视图控制器。这是因为每个tableView都在查看相同的委托方法,如果它们在同一个视图控制器中,则委托方法必须区分tableViews。委托方法具有允许此操作的签名,但是根据我的经验,这可能会导致代码设计混乱,难以跟踪和管理。

另一方面,您可能有两个表格由同一个视图控制器管理,其中一个表格填充有有意义的数据,而另一个表格只是一个占位符(当数据源为空时)。其中一个可能可见,而另一个则不可见。当两个表格都由相同的数据源(模型)驱动时,为什么要创建两个视图控制器来使生活变得复杂呢?

在我看来,这归结为代码的难以跟踪和管理的复杂性。如果使用单个视图控制器变得繁琐,则考虑使用更多的视图控制器。

更新

顺便说一下,我目前正在处理的一个示例可能会说明类似的情况。在许多开发人员使用的InAppSettingsKit中,有几个用于主视图片段的xib文件。您可以在github上查看此结构。有一个主视图控制器和几个xib文件。(还有我称之为“助手”视图控制器和电子邮件组合器视图控制器。)在这个示例中,xib文件可以多次用于指定表格视图单元格的布局。但是,并没有为每个xib文件创建视图控制器。(InAppSettingsKit的文档很少,因此仅通过快速查看可能不明显。)


那么对于我的使用情况,我将视图拆分为单独的nib文件的唯一原因是为了更轻松地在IB中管理这些视图,您认为我的方法是否安全可靠,或者它是否违反了苹果的指南? - Camsoft
在你所做的事情方面,没有任何规则或指导方针。在这方面你做得很好。 - Jim
我添加了一个许多开发人员使用的真实软件组件的示例。有关更多详细信息,请参见我的上面的答案。 - Jim
谢谢Jim。只是想确保我没有做什么疯狂的事情。 - Camsoft

0

实际上这是可以做到的。

打开你的.xib文件,选择File's Owner(在占位符中)-> "identity inspector"(工具)-> 将类名更改为你的控制器类名 -> 按住control键并将文件所有者占位符拖动到View对象上,在对话框中选择“view”。 现在你可以自定义你的视图了。

p.s. 你可以使用与第一个xib相同的outlets,只需要将它们拖到新的xib中(+control键)。

这里有一个详细的教程: http://irawd.wordpress.com/2013/09/05/how-to-link-a-xib-file-to-a-class-and-use-2-xib-files-for-iphone4-and-iphone5/


在SO上发布链接可能很好,但链接往往会丢失...请在答案正文中发布关键要素。 - NirMH
@NirMH编辑。感谢您的反馈,这是我在SO上的第一个答案。 - user3206558

0
每个视图都应该有一个相应的UIViewController。使用一个ViewController来“控制”多个视图会破坏MVC范例。从一个控制器“控制”多个“视图”会使更改其中一个事物变得更加困难,而不破坏其他事物。关于如何向最终用户呈现内容所做的选择将因每个人而异。因此,如果说导航控制器在您的情况下无法起作用,也许模态视图是答案,或者您可以实例化自定义的UIViewControllers并将它们添加到您的视图([addSubview:]),如果这是您想要的方法,但是正如我所说,为每个视图对象制作一个“控制器”以及相应的xib会对您有益。如果需要发送信息,请使用委托或使用通知将消息发送回父视图。我曾经吃过MVC范例教训,它会让你的生活变得很痛苦。尝试尽可能保持代码解耦。并阅读有关MVC设计模式的相关资料,您不会后悔。

所有的子视图都与单个屏幕相关,因此只需要一个视图控制器。我本可以将所有的子视图都添加到同一个nib文件中,但是就像我所说的那样,这样会变得混乱且难以布局,因为视图会重叠。我的想法是将一些视图分解成单独的nib文件,然后使用视图控制器的viewDidLoad方法将它们加载回主视图中。 - Camsoft
每个视图都应该有对应的UIViewController。使用一个ViewController来“控制”多个视图会破坏MVC范式。如果这是真的,那么通用视图控制器如何工作呢?它有2个nibs。 - Juan
我和 @Hubert 的想法几乎一样。这似乎存在一些问题。如果决定是在运行时进行的,并且是在按钮单击上进行的,那么这是否意味着 xib 将在后台加载,实际上所有的 xib 都会被加载,然后选择其中一个?此外,自动布局可以轻松解决这个问题。 - Ali Abbas Jaffri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接