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

Posted

技术标签:

【中文标题】在单个视图控制器中使用多个 nib 文件?【英文标题】:Using multiple nib files with a single view controller? 【发布时间】:2012-01-12 17:50:47 【问题描述】:

背景

我正在使用界面构建器为我正在开发的应用程序创建 UI。该应用程序有一个显示一系列按钮的屏幕。单击按钮会显示覆盖按钮的关联视图。单击另一个按钮会隐藏上一个覆盖视图并显示另一个。

在 IB 中管理 UI 也更容易,我决定为单击相关按钮时出现的每个子视图创建多个 nib 文件。然后,我使用 UINib 类在视图控制器的 viewDidLoad 方法中加载子视图的 nib 文件。

这背后的想法是避免在单个 nib 文件中堆叠多个视图,因为这在 IB 中很难操作。我本可以在代码中创建所有视图,但这需要大量繁琐的编码,因为每个子视图的布局都非常复杂(有多个子视图)。

从 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 文件,用于在视图控制器的 viewDidLoad 方法中加载的子视图。

问题!

很抱歉介绍太长,但我想非常清楚我在做什么。

我的方法不好还是不寻常? 这样做有什么潜在的问题吗? 当其他人需要动态界面和 仍想将所有内容保留在 Interface Builder 中?

备注

在有人问我为什么不在新屏幕上显示子视图并使用导航栏之前,让我说我有很好的理由并且我确实了解 ios UI 指南。上面的用例并不完全是我的用例,但它清楚地描述了问题而不会陷入我的开发应用程序中。

此外,我知道我可以将所有子视图编写为代码,但每个子视图都有复杂的子视图布局,并且要尝试使它们看起来正确,会需要大量代码和混乱。

提前致谢。

【问题讨论】:

【参考方案1】:

视图控制器和视图之间不一定是一对一的关系。大多数视图包含许多子视图,它们本身就是视图,所以这实际上没有意义。

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

例如,如果您有两个 sbuview,每个都是 tableView,您可能希望每个 tableView 有一个视图控制器。这是因为每个 tableView 都在查看相同的委托方法,如果它们在同一个 viewController 中,那么委托方法必须区分 tableView。委托方法具有允许这样做的签名,但根据我的经验,它确实会造成难以遵循和管理的混乱代码设计。

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

在我看来,这归结为遵循和管理代码的难度。如果使用单个视图控制器的复杂性变得繁重,请考虑使用更多视图控制器。

更新

顺便说一句,我有一个我目前正在使用的示例,它可能说明了类似的情况。在许多开发人员使用的 InAppSettingsKit 中,有几个 xib 文件用于主视图的各个部分。 You can look at the structure here on github。有一个主视图控制器和几个 xib 文件。 (还有我称之为“助手”视图控制器和电子邮件编写器视图控制器的东西。)在这个例子中,xib 文件可以多次用于指定表格视图单元格的布局。但是,每个 xib 文件都没有视图控制器。 (InAppSettingsKit 的文档很少,所以这些东西可能只是快速浏览一下就不是很明显。)

【讨论】:

所以对于我的用例,我将视图拆分为单独的 nib 文件的唯一原因是为了更容易在 IB 中管理这些视图,您认为我的方法使用安全吗?违反 Apple 的指导方针? 没有关于你在做什么的规则或指南。在这方面你很好。 我添加了一个许多开发人员使用的真实软件组件的示例。有关详细信息,请参阅我上面的答案。 谢谢吉姆。只是想确保我没有做一些疯狂的事情。【参考方案2】:

每个 View 都应该有一个对应的 UIViewController。使用一个 ViewController 来“控制”多个视图打破了 MVC 范式。从一个控制器“控制”多个“视图”将使在不破坏其他内容的情况下更改一件事变得更加困难。您对如何向最终用户呈现内容所做的选择因人而异。因此,如果您说 NavigationController 在您的情况下不起作用,也许 Modal 视图就是答案,或者您可能只是实例化您的自定义 UIViewControllers 并将它们添加到您的视图中([addSubview:]),如果那是您想要的道路,但就像我说的那样,为每个视图对象以及相应的 xib 创建一个“控制器”对您是有益的。如果您需要发回信息,请使用委托或使用通知将消息发送回父视图。我学到了不遵循 MVC 范式会让你的生活变得悲惨的艰难方式。尽量保持你的代码解耦。并阅读 MVC 设计模式,您不会后悔的。

【讨论】:

所有子视图都与单个屏幕相关,因此是单个视图控制器。我本可以轻松地将所有子视图添加到同一个 nib 文件中,但就像我说的那样,由于视图重叠,它变得混乱且难以布局。我的想法是将一些视图分解为单独的 nib 文件,然后使用视图控制器的 viewDidLoad 方法将它们加载回主视图。 每个View都应该有一个对应的UIViewController。使用一个 ViewController 来“控制”多个视图打破了 MVC 范式。如果这是真的,通用视图控制器如何工作?它有 2 个笔尖。 我在想几乎同样的事情@Hubert。似乎有一些与此相关的问题。如果决定是在运行时和单击按钮时做出的,这是否意味着 xib 将在后台加载,实际上所有这些都将被选中?此外,自动布局可以轻松解决问题。【参考方案3】:

实际上它可以做到这一点。

打开你的.xib文件,选择文件的所有者(在占位符中)->“身份检查器”(实用程序)->将类名更改为您的控制器类名->按下控制并将文件的所有者占位符拖动到查看对象,选择“查看“在对话框中。 现在您可以自定义视图。

附言您可以使用与第一个 xib 相同的插座,只需将它们拖到新的 xib(+control sure)。

这是一个解释性教程: 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 已编辑。感谢您的反馈,这是我对 SO 的第一个回答

以上是关于在单个视图控制器中使用多个 nib 文件?的主要内容,如果未能解决你的问题,请参考以下文章

访问,从单个 nib 获取对多个视图的引用

为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib

Core Data 文档基于多个 nib 基于选择

尝试使用 .nib 加载视图控制器失败

如何在不使用视图控制器的情况下使用 nib 文件加载视图

是否可以在 nib 中使用视图控制器?还是只是 UIViews?