个性化阅读
专注于IT技术分析

iOS用户界面:故事板,NIB和自定义代码

本文概述

我经常听到iOS开发人员询问相同关键问题的一些变化形式:

在iOS中开发UI的最佳方法是:通过故事板, NIB或代码?

对这个问题的回答, 无论是显式的还是隐式的, 都倾向于假定在开发之前要做出一个互斥的选择, 通常是预先解决的。

我认为答案应该采取一个或多个反问的形式。

什么是”最佳”汽车?

让我用一个离题的例子来解释。假设我要购买汽车, 然后问一个简单的问题:”最佳选择是什么?”

你能通过建议模特甚至品牌来回答问题吗?除非你建议使用法拉利, 否则不太可能。相反, 你可能会回答其他一些问题, 例如:

  • 你的预算是多少?
  • 你需要几个座位?
  • 你关心油耗吗?
  • 你对跑车有什么感觉?

显然, 除非放在适当的环境中, 否则没有好车或坏车之类的东西-根据特定需求而定的好车或坏车。

返回iOS UI设计

就像我们的汽车咨询一样, “开发iOS UI的最佳方法是什么”问题也没有上下文。令人惊讶的是, 答案不必是万能的。

概括地说, 你可以采用三种类型的用户界面设计方法, 每种方法都有其优缺点, 其支持者和讨厌者:

  • iOS Storyboards:一种视觉工具, 用于布置多个应用程序视图以及它们之间的过渡。
  • NIB(或XIB):每个NIB文件都对应一个视图元素, 并且可以在Interface Builder中进行布局, 使其也成为可视化工具。请注意, 名称” NIB”源自文件扩展名(以前的.nib现在是.xib, 尽管旧的发音仍然存在)。
  • 自定义代码:即没有GUI工具, 而是以编程方式处理所有自定义位置, 动画等。

这些选择都没有一个比其他任何一个都更好的了(尽管你可能会听到)。

例如, 情节提要是iOS UI工具箱的最新功能。有人告诉我它们是未来, 它将取代NIB和自定义代码UI。我认为情节提要是一个有用的工具, 但它并不能替代NIB和自定义代码。在某些情况下(但并非在所有情况下), 故事板是正确的选择。

此iOS开发教程旨在探讨iOS UI设计的三种方法之间的区别。

此外, 当可以全部使用它们(在同一项目中)时, 为什么要静态地选择一个选项, 而选择最适合当前特定问题的机制呢?

我认为这是一个更高层次的问题, 其答案在我的软件开发原则列表中排名很高:没有通用的语言, 框架或技术是每个人的通用最佳选择。软件开发问题。 iOS UI设计也是如此。

在本iOS开发教程中, 我们将探讨每种方法, 并介绍应该和不应该使用它们的用例, 以及将它们融合在一起的方式。

iOS故事板

初学者的经典错误是创建一个大型的项目范围内的iOS Storyboard。刚开始使用Storyboard时, 我也犯了这个错误(可能是因为这是一个诱人的选择)。

初学者的一个典型错误是创建一个在整个项目范围内的大型Storyboard。故事板是一个要讲故事的板。它不应该用于将无关的故事混合在一起。

顾名思义, 情节提要是一个讲故事的讲板。不应将它与大量无关的故事混合使用。故事板应包含在逻辑上相互关联的视图控制器, 这并不意味着每个视图控制器。

例如, 在处理时使用情节提要很有意义:

  • 一组用于身份验证和注册的视图。
  • 多步骤订单输入流程。
  • 类似于向导(即教程)的流程。
  • 一组主要细节视图(例如, 配置文件列表, 配置文件详细信息)。

同时, 应避免使用大型Storyboard, 包括单个应用程序范围内的Storyboard(除非应用程序相对简单)。在深入探讨之前, 让我们看看原因。

大型iOS故事板的愚蠢

除了难以浏览和维护之外, 大型情节提要板还给团队环境增加了一层复杂性:当多个开发人员同时处理同一个情节提要文件时, 源代码控制冲突是不可避免的。尽管情节提要板在内部表示为文本文件(实际上是XML文件), 但合并通常并非易事。

当开发人员查看源代码时, 他们将其归为语义。因此, 在手动合并时, 他们可以阅读和理解冲突的两面并采取相应的措施。相反, 情节提要是Xcode管理的XML文件, 每一行代码的含义并不总是很容易理解。

让我们举一个非常简单的例子:假设两个不同的开发人员更改了UILabel的位置(使用自动布局), 而后者则推动了他的更改, 从而产生了这样的冲突(请注意id属性冲突):

<layoutGuides>
    <viewControllerLayoutGuide type="top" id="ar5-ed-tdC"/>
    <viewControllerLayoutGuide type="bottom" id="enX-PS-xZQ"/>
</layoutGuides>

<layoutGuides>
    <viewControllerLayoutGuide type="top" id="6cK-2r-Dvq"/>
    <viewControllerLayoutGuide type="bottom" id="EbB-ky-ghh"/>
</layoutGuides>

ID本身并不能提供任何关于其真实含义的指示, 因此你无需任何操作。唯一有意义的解决方案是选择冲突的两个方面之一, 而抛弃另一个。会不会有副作用?谁知道?不是你。

为了缓解这些iOS界面设计问题, 建议在同一项目中使用多个情节提要。

何时使用情节提要

故事板最好与多个互连的视图控制器一起使用, 因为它们的主要简化是在视图控制器之间进行转换。在某种程度上, 它们可以被认为是视图控制器之间具有视觉和功能流的NIB的组合。

故事板最好与多个互连的视图控制器一起使用, 因为它们的主要简化是在视图控制器之间进行转换。

除了简化导航流程之外, 另一个明显的优势是它们消除了弹出, 推送, 呈现和关闭视图控制器所需的样板代码。此外, 视图控制器是自动分配的, 因此无需手动分配和初始化。

最后, 虽然情节提要板最适合用于涉及多个视图控制器的场景, 但出于以下三个原因, 在使用单个表视图控制器时使用情节提要板也是可取的:

  • 就地设计表格单元原型的能力有助于将各个部分保持在一起。
  • 可以在父表视图控制器内部设计多个单元格模板。
  • 可以创建静态表格视图(令人期待已久的添加, 但不幸的是, 仅在情节提要中可用)。

可能有人争辩说, 也可以使用NIB设计多个单元模板。实际上, 这只是一个优先事项:有些开发人员喜欢将所有内容都放在一个地方, 而其他人则不在乎。

何时不使用iOS故事板

几种情况:

  • 该视图具有复杂的或动态的布局, 最好用代码实现。
  • 该视图已使用NIB或代码实现。

在这些情况下, 我们可以将视图放在情节提要中, 也可以将其嵌入到视图控制器中。前者打破了Storyboard的视觉流程, 但没有任何负面的功能或开发意义。后者保留了这种视觉流程, 但由于视图未集成到视图控制器中, 因此需要额外的开发工作:它只是作为组件嵌入的, 因此视图控制器必须与视图交互而不是实现视图。

一般利弊

现在, 我们已经知道情节提要何时在iOS UI设计中有用, 并且在继续学习本教程中的NIB之前, 让我们先看一下它们的一般优缺点。

优点:性能

直观地, 你可以假定加载情节提要时, 将立即实例化其所有视图控制器。幸运的是, 这只是实际实现的一种抽象, 而不是真实的:相反, 仅创建初始视图控制器(如果有)。其他视图控制器是在执行segue时或从代码手动地动态实例化的。

优点:原型

故事板可简化用户界面和流程的原型制作和模拟。实际上, 可以使用情节提要和仅几行代码轻松实现具有视图和导航功能的完整的原型应用程序。

缺点:可重用性

在移动或复制时, iOS故事板的位置不正确。必须将情节提要板及其所有从属视图控制器一起移动。换句话说, 单个视图控制器不能作为单个独立实体单独提取和重用。它取决于Storyboard其余部分的功能。

缺点:数据流

应用转换时, 通常需要在视图控制器之间传递数据。但是, 在这种情况下, 情节提要的视觉流程中断了, 因为在Interface Builder中没有发生这种情况的痕迹。故事板负责处理视图控制器之间的流, 但不处理数据流。因此, 目标控制器必须配置代码, 以覆盖视觉体验。

故事板负责处理视图控制器之间的流, 但不处理数据流。

在这种情况下, 我们必须依靠带有if / else-if框架的prepareForSegue:sender, 如下所示:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    NSString *identifier = [segue identifier];
    if ([identifier [email protected]"segue_name_1"]) {
        MyViewController *vc = (MyViewController *) [segue destinationViewController];
        [vc setData:myData];
    } else if ([identifier [email protected]"segue_name_2"]) {
        ...
    } else if ...
}

我发现这种方法容易出错并且不必要地冗长。

NIB

NIB是执行iOS界面设计的较旧方法。

在这种情况下, “旧”并不表示”不好”, “过时”或”已弃用”。实际上, 了解iOS Storyboard并不是NIB的通用替代品非常重要;在某些情况下, 它们只是简化了UI的实现。

使用NIB, 可以设计任何任意视图, 然后开发人员可以根据需要将其附加到视图控制器。

如果我们将面向对象的设计应用于我们的UI, 则有必要将视图控制器的视图分解为单独的模块, 每个模块都通过具有自己的NIB文件(或将多个模块分组到同一文件中)实现为视图。这种方法的明显优势是每个组件都更易于开发, 更易于测试和易于调试。

NIB共享我们在情节提要中看到的合并冲突问题, 但程度较小, 因为NIB文件的规模较小。

何时将NIB用于iOS UI设计

所有用例的子集为:

  • 模态视图
  • 简单的登录和注册视图
  • 设定值
  • 弹出式视窗
  • 可重用的视图模板
  • 可重复使用的表格单元格模板

与此同时…

何时不使用NIB

你应避免将NIB用于以下用途:

  • 具有动态内容的视图, 其中布局会根据内容而发生很大变化。
  • 本质上不容易在Interface Builder中设计的视图。
  • 具有复杂过渡的视图控制器可以通过情节提要进行简化。

一般利弊

更笼统地说, 让我们逐步了解使用NIB的利弊。

优点:可重用性

当在多个类之间共享相同的布局时, NIB会派上用场。

作为一个简单的用例, 可以使用假设的TTLoginView和TTSignupView视图实现包含用户名和密码文本字段的视图模板, 这两个视图都可以源自同一NIB。 TTLoginView必须隐藏密码字段, 并且都必须指定相应的静态标签(例如”输入你的用户名”与”输入你的密码”), 但是标签将具有相同的基本功能和相似的布局。

优点和缺点:效果

NIB是延迟加载的, 因此它们只有在需要时才使用内存。虽然这可能是一个优点, 但延迟加载过程会有所延迟, 这也有不利之处。

iOS自定义代码(程序化UI)

可以使用情节提要和NIB完成的所有iOS界面设计也可以使用原始代码来实现(当然, 有时候开发人员没有这么丰富的工具集)。

NIB和情节提要板无法完成的工作始终可以通过代码来实现。

也许更重要的是, 始终可以使用代码来实现NIB和Storyboard所不能完成的工作, 当然, 前提是要在技术上可行。另一种看待它的方式是NIB和Storyboard是用代码实现的, 因此它们的功能自然是其中的一个子集。让我们直接了解利弊。

优点:引擎盖下

以编程方式创建iOS UI的最大优势是:如果你知道如何编写用户界面代码, 那么你就会知道幕后的情况, 而NIB和Storyboard并不一定是如此。

进行比较:计算器是一个有用的工具。但是知道如何手动执行计算并不是一件坏事。

这不仅限于iOS, 还限于任何可视RAD工具(例如, Visual Studio和Delphi, 仅举几例)。可视HTML RAD环境代表了一个典型的临界情况:它们用于生成(通常写得不好)代码, 声称不需要HTML知识, 并且所有内容都可以在视觉上完成。但是, 没有一个Web开发人员会在不弄脏双手的情况下实现一个Web页面:他们知道手动处理原始HTML和CSS将导致模块化, 更高效的代码。

因此, 掌握iOS用户界面的编码可让你更好地控制这些组件, 以及如何将它们组合在一起, 从而提高了你作为开发人员的能力。

Pro:当代码是唯一的选择时

在某些情况下, 自定义iOS代码是UI设计的唯一选择。典型的示例是动态布局, 其中视图元素会四处移动, 流程或布局会根据内容进行重大调整。

优点:合并冲突

尽管NIB和Storyboard遭受合并冲突的困扰很大, 但是代码却没有相同的错误。所有代码都具有语义, 因此解决冲突并不比平时困难。

特色:原型制作

在你看到实际的布局之前, 很难弄清楚它的外观。此外, 你无法在视觉上放置视图和控件的位置, 因此与NIB和Storyboard相比, 将布局规格转换为有形视图可能需要更长的时间, 而NIB和Storyboard可以让你即时预览事物的呈现方式。

特点:重构

重构很久以前或其他人编写的代码也变得更加复杂:使用自定义方法和幻数对元素进行定位和动画处理时, 调试会话可能会变得很艰巨。

优点:性能

在性能方面, 情节提要和NIB会受到加载和解析的开销;最后, 它们被间接翻译成代码。不用说, 代码生成的UI不会发生这种情况。

优点:可重用性

可以以可重用的方式设计以编程方式实现的任何视图。让我们看一些用例:

  • 两个或多个视图具有相同的行为, 但是它们略有不同。一个基类和两个子类可以很好地解决该问题。
  • 必须创建一个项目, 目的是创建单个代码库, 但要生成两个(或多个)不同的应用程序, 每个应用程序都具有特定的自定义设置。

使用NIB和Storyboard, 相同的UI设计过程将更加复杂。模板文件不允许继承, 并且可能的解决方案限于以下几种:

  • 复制NIB和Storyboard文件。此后, 他们有各自的生活, 并且与原始文件没有任何关系。
  • 用代码覆盖外观和行为, 这可能在简单的情况下起作用, 但可能导致其他情况下的严重复杂化。大量使用代码覆盖也可能使可视化设计变得无用, 并演变成令人头疼的问题, 例如, 当某个控件在Interface Builder中以一种方式显示时, 而在应用程序运行时看起来却完全不同。

何时使用代码

在以下情况下, 通常最好使用自定义代码进行iOS用户界面设计:

  • 动态布局。
  • 具有效果的视图, 例如圆角, 阴影等。
  • 使用NIB和情节提要的任何情况都是复杂或不可行的。

何时不使用代码

通常, 始终可以使用代码制作的UI。他们很少是一个坏主意, 所以我在这里放一个。

尽管NIB和Storyboard可以带来一些优势, 但我认为我没有任何不利的方面, 我可以列出清单来阻止代码使用(也许是懒惰)。

一个项目, 多个工具

故事板, NIB和代码是用于构建iOS用户界面的三种不同工具。我们很幸运有他们。程序化UI的狂热者可能不会考虑其他两个选项:通过代码, 你可以进行技术上可行的一切, 而替代方法则有其局限性。对于在那里的其他开发人员, Xcode军刀提供了三个工具, 可在同一项目中一次有效地全部使用它们。

你怎么问?但是你喜欢。以下是一些可能的方法:

  • 将所有相关屏幕分组到单独的组中, 并用各自不同的Storyboard实现每个组。
  • 在表格视图控制器内部, 使用情节提要板就地设计不可重复使用的表格单元。
  • 在NIB中设计可重用的表格单元, 以鼓励重用和避免重复, 但可通过自定义代码加载这些NIB。
  • 使用NIB设计自定义视图, 控件和中间对象。
  • 使用代码来实现高度动态的视图, 更一般地, 将代码用于无法通过情节提要和NIB实现的视图, 同时在情节提要中容纳视图过渡。

最后, 让我们看一个最后的示例, 将其联系在一起。

一个简单的用例

假设我们要开发一个具有几种不同视图的基本消息传递应用程序:

  • 关注的朋友列表(具有可重复使用的单元格模板, 以使UI在以后的列表中保持一致)。
  • 配置文件详细信息视图, 分为单独的部分(包括配置文件信息, 统计信息和工具栏)。
  • 发送给朋友和从朋友接收的消息的列表。
  • 新的消息表单。
  • 标签云视图, 显示用户消息中使用的不同标签, 每个标签的大小与使用次数成正比。

另外, 我们希望视图按如下方式流动:

  • 单击关注的朋友列表中的一个项目, 将显示相关朋友的个人资料详细信息。
  • 配置文件详细信息显示了配置文件名称, 地址, 统计信息, 最新消息的简短列表以及工具栏。

为了实现此iOS应用, 我们可以使用以下所有三个UI工具:

  • 具有四个视图控制器的情节提要(列表, 详细信息, 消息列表和新消息表单)。
  • 可重复使用的配置文件列表单元格模板的单独的NIB文件。
  • 配置文件详细信息视图的三个独立的NIB文件, 组成该文件的每个单独部分(配置文件详细信息, 统计信息, 最后三个消息)各一个, 以实现更好的可维护性。这些NIB将被实例化为视图, 然后添加到视图控制器中。
  • 标签云视图的自定义代码。该视图是不能通过StoryBoards或NIB不能在Interface Builder中设计的视图的典型示例。相反, 它是通过代码完全实现的。为了保持情节提要的视觉流, 我们选择向情节提要添加一个空的视图控制器, 将标签云视图实现为独立视图, 然后以编程方式将该视图添加到视图控制器。显然, 该视图也可以在视图控制器内部实现, 而不是作为独立的视图实现, 但是我们将它们分开以便更好地重用。

一个非常基本的模型可能看起来像:

该图说明了一个使用情节提要,NIB和自定义iOS代码的iOS用户界面设计项目。

因此, 我们概述了一个相当复杂的iOS应用的基本结构, 其核心视图将我们的三种主要UI设计方法联系在一起。请记住:由于每种工具都有其优缺点, 因此没有二元决策。

本文总结

如本教程所述, 情节提要板为iOS UI设计和视觉流程带来了明显的简化。它们还消除了样板代码;但所有这些都是要付出代价的, 要付出灵活性。同时, NIB通过聚焦于单个视图而没有视觉流动, 从而提供了更大的灵活性。当然, 最灵活的解决方案是代码, 它往往不友好并且本质上是不可视的。

如果你对本文感兴趣, 我强烈建议你观看Ray Wenderlich的精彩辩论, 该辩论花了55分钟, 讨论了NIB, Storyboard和代码制作的UIS。

最后, 我想强调一件事:避免不惜一切代价使用不正确的iOS UI设计工具。如果视图无法使用情节提要进行设计, 或者可以使用NIB或代码以更简单的方式实现, 请不要使用情节提要。同样, 如果无法使用NIB设计视图, 请不要使用NIB。这些规则虽然简单, 但对你作为开发人员的教育将大有帮助。

赞(0)
未经允许不得转载:srcmini » iOS用户界面:故事板,NIB和自定义代码

评论 抢沙发

评论前必须登录!