作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
安东尼奥·贝洛的头像

安东尼奥·贝罗

拥有20年以上各种技术经验的多面手, 现在主要关注iOS, 斯威夫特, Objective C和后端

专业知识

以前在

斯威夫特lane
分享

我经常听到 iOS开发者 问一些相同关键问题的变体:

在iOS中开发UI的最佳方式是什么:通过故事板、nib还是代码?

这个问题的答案, 或明或暗, 倾向于假设存在一个互斥的选择, 一个经常被预先处理的问题, 在开发之前.

我认为答案应该是一个或多个 计数器 问题.

“最好”的车是什么?

让我用一个离题的例子来解释. 比如说我想买一辆车,我问你一个简单的问题:“什么是最好的选择??”

你真的能通过提出一个模型来回答这个问题吗 品牌? 不太可能,除非你建议开法拉利. 相反,你可能会用其他几个问题来回答,比如:

  • 你的预算是多少??
  • 您需要几个座位?
  • 你关心燃油消耗吗?
  • 你觉得跑车怎么样?

很明显,根本就没有 or 汽车,除非它被放置在适当的环境中——根据特定的需求,只有好车或坏车.

回到iOS UI设计

就像我们的汽车询价一样 “开发iOS UI的最佳方法是什么?” 问题缺乏背景. 令人惊讶的是,答案不一定是一个包罗万象的案例.

一般来说, 您可以采用三种类型的用户界面设计方法, 每一种都有其利弊, 它的支持者和反对者:

  • iOS故事板:一个可视化工具,用于布局多个应用程序视图和它们之间的转换.
  • nib(或xib):每个NIB文件对应一个视图元素,可以在Interface Builder中布局, 让它成为一个可视化的工具. 请注意,名称“NIB”派生自文件扩展名(前面) .笔尖和现在 .Xib,尽管旧的发音仍然存在).
  • 自定义代码: i.e., no GUI 工具,而是处理所有自定义定位,动画等. 以编程方式.

这些选择都不普遍 更好的 比其他任何一个(不管你可能听到什么).

故事板,例如,是iOS UI工具包的最新成员. 我被告知它们是未来,它们将取代nib和自定义代码ui. 我认为故事板是一个有用的工具,但并不是 更换 作为一个 补充 用于nib和自定义代码. 故事板在某些情况下是正确的选择,但不是所有情况.

本iOS开发教程旨在探讨iOS UI设计的3种方法之间的差异.

进一步, 当您可以在同一个项目中使用所有选项时,为什么要静态地坚持使用单个选项呢?, 选择最适合手头特定问题的机制?

这是一个可以, 在我看来, 泛化的:在更高层次上泛化的, 他的答案在我的软件开发原则列表中排名很高: 世界上没有通用的语言, 框架, 或者技术是每个软件开发问题的通用最佳选择. iOS UI设计也是如此.

在这个iOS UI设计教程, 我们将探索这些方法中的每一种,并介绍它们应该使用和应该使用的用例 被雇用,以及它们可以混合在一起的方式.

iOS故事板

一个典型的新手错误是创建一个大型的项目范围的iOS故事板. 我刚开始的时候也犯过这个错误 使用故事板 (可能是因为这条路很诱人。). 如果你需要在继续之前了解基本知识,你可以咨询苹果公司 iOS storyboard教程.

一个典型的初学者错误是创建一个大型的项目范围的故事板. 故事板是一个有故事要讲的板. 它不应该被用来把不相关的故事混合成一大卷.

顾名思义,故事板是一个 带着一个故事登机. 它不应该被用来把不相关的故事混合成一大卷. 故事板应该包含逻辑上彼此相关的视图控制器——这并不意味着 每一个 视图控制器.

例如,在处理以下问题时使用故事板是有意义的:

  • 一组用于身份验证和注册的视图.
  • 多步骤订单输入流程.
  • 一个巫师般的(i.e.(教程)流程.
  • 视图的主-细节集(例如.g.、配置文件列表、配置文件详细信息).

与此同时, 应该避免使用大型故事板, 包括单个应用程序范围的故事板(除非应用程序相对简单). 在我们深入讨论之前,让我们看看原因.

大型iOS故事板的愚蠢之处

大故事板, 除了难以浏览和维护, 给团队环境增加一层复杂性:当多个开发人员同时在同一个故事板文件上工作时, 源代码控制冲突是不可避免的. 故事板在内部表示为文本文件(XML文件), 实际上), 合并通常是非琐碎的.

当开发人员查看源代码时,他们会赋予其语义含义. 手动合并时, 他们能够阅读和理解冲突的双方,并采取相应的行动. 故事板, 而不是, XML文件是由Xcode管理吗, 而且每行代码的含义并不总是容易理解的.

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


    
    



    
    

id 它本身并没有提供任何关于它真正意义的指示, 所以你没什么可做的了. 唯一有意义的解决办法是选择冲突双方中的一方,抛弃另一方. 会有副作用吗? 谁知道? 不是你.

来缓解这些iOS界面设计问题, 在同一个项目中使用多个用户故事板是推荐的方法.

何时使用故事板

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

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

除了简化导航流程, 另一个明显的优点是它们消除了弹出所需的样板代码, 推, 现在, 然后解散视图控制器. 此外,视图控制器是自动分配的,所以不需要手动分配 alloc初始化.

最后, 而故事板最适合用于涉及多个视图控制器的场景, 使用故事板也是合理的 表视图控制器的三个原因:

  • 就地设计表格单元格原型的能力有助于将各个部分组合在一起.
  • 可以在父表视图控制器中设计多个单元格模板.
  • 创建静态表视图是可能的(一个期待已久的附加功能,不幸的是只在故事板中可用).

有人可能会说,也可以使用nib设计多个单元格模板. 事实上, 这只是一个偏好问题:一些开发人员更喜欢将所有东西放在一个地方, 而其他人则不在乎.

使用iOS故事板

有几个例子:

  • 视图具有复杂或动态的布局,最好使用代码实现.
  • 视图已经用nib或代码实现了.

在这些情况下,我们可以把视图留在故事板之外或者嵌入到视图控制器中. 前者破坏了故事板的视觉流, 但不会对功能或发展产生任何负面影响. 后者保留了这种视觉流, 但是它需要额外的开发工作,因为视图没有集成到视图控制器中:它只是作为一个组件嵌入, 因此,视图控制器必须与视图交互,而不是实现它.

一般利弊

现在我们知道故事板在iOS中什么时候有用了 用户界面设计, 在我们继续本教程中的nib之前, 让我们来看看它们的一般优点和缺点.

职业:性能

直观地, 你可以假设当一个故事板被加载时, 它的所有视图控制器都会立即实例化. 幸运的是,这只是一个抽象概念 实际实现为True:相反,只创建初始视图控制器(如果有的话). 其他视图控制器是动态实例化的, 要么在segue执行时执行,要么在代码中手动执行.

正方观点:原型

故事板简化了用户界面的原型和模拟 流. 实际上, 使用斯威夫特故事板和几行代码就可以很容易地实现带有视图和导航的完整的工作原型应用程序.

反对:可重用性

当涉及到移动或复制时,iOS故事板的定位很差. 故事板必须与其所有依赖的视图控制器一起移动. 换句话说, a 单 视图控制器 can不 be individually extracted 和 reused elsew在这里 作为一个 单 independent entity; it’s dependent on the rest of the 故事板 to function.

缺点:数据流

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

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

在这种情况下,我们不得不依靠 prepareForSegue:发送方,使用如下的if/else-if框架:

- (void) prepareForSegue:(UI故事板Segue *)segue sender:(id)sender {
    NSString *identifier = [segue identifier];
    if ([identifier isEqualToString@"segue_name_1"]) {
        MyViewController *vc = (MyViewController *) [segue destinationViewController];
        (vc setData: myData);
    } else if ([identifier isEqualToString@"segue_name_2"]) {
        ...
    } else if ...
}

我发现这种方法容易出错,而且不必要地冗长.

傲慢的人

nib是执行iOS界面设计的老方法.

在这种情况下,“旧的”并不意味着“坏的”、“过时的”或“废弃的”。. 事实上, it’s important to underst和 that iOS故事板 aren’t a universal 更换 for 傲慢的人; they just simplify the UI implementation in 一些 情况下.

与上司, 可以设计任意视图, 开发人员可以根据需要将其附加到视图控制器上.

如果我们将面向对象的设计应用于我们的ui, 那么将视图控制器的视图分解为 不同的模块, 每个都实现为带有自己NIB文件的视图(或者将多个模块分组到同一个文件中)。. 这种方法的明显优点是每个组件都更容易开发, 更容易测试, 更容易调试.

nib分享了我们在故事板中看到的合并冲突问题, 但程度较轻, 因为NIB文件的操作规模较小.

何时在iOS UI设计中使用nib

所有用例的一个子集是:

  • 模态视图
  • 简单的登录和注册视图
  • 设置
  • 弹出窗口
  • 可重用视图模板
  • 可重用的表格单元格模板

与此同时……

使用nib

您应该避免在以下情况下使用nib:

  • 具有动态内容的视图,其中布局会根据内容发生显著变化.
  • 在接口生成器中不容易设计的视图.
  • 具有复杂过渡的视图控制器可以用iOS故事板简化.

一般利弊

更一般地说,让我们来看看使用nib的优缺点.

正方观点:可重用性

当跨多个类共享相同的布局时,nib会派上用场.

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

箴 & 缺点:性能

傲慢的人是 延迟加载,所以他们只有在必要的时候才会使用内存. 虽然这可能是一个优势, 延迟加载过程有延迟, 这也是一种不利因素.

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

任何 iOS界面设计 这可以用故事板完成,nib也可以用原始代码实现(曾经有一段时间), 当然, 当开发人员没有这么丰富的工具时).

nib和故事板不能做的事情总是可以用代码实现.

也许更重要的是, nib和故事板无法完成的事情总是可以通过代码提供来实现, 当然, 技术上是可行的. 另一种看待它的方式是nib和故事板是用代码实现的, 所以它们的功能自然是一个子集. 让我们直接进入正反两方面.

正方:引擎盖下

以编程方式创建iOS UI的最大优势: 如果您知道如何编写用户界面,那么您就知道幕后发生了什么,而nib和故事板则不一定如此.

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

这并不局限于iOS,也适用于任何可视化的RAD工具.g., Visual Studio和Delphi,仅举几例). 可视化HTML RAD环境代表了一种典型的边界情况:它们用于生成(通常编写得很差的)代码, 声称不需要HTML知识, 一切都可以用视觉来完成. 但是没有一个web开发人员会在不动手的情况下实现一个网页:他们知道手工处理原始的HTML和CSS会导致更多的模块化, 更高效的代码.

So, 掌握iOS用户界面的编码可以让你更好地控制和了解这些部分是如何组合在一起的, 这提高了你作为开发人员的上限.

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

在某些情况下,自定义iOS代码是UI设计的唯一选择. 动态布局, 视图元素在哪里移动,流或布局根据内容进行显著调整, 都是典型的例子.

利:合并冲突

而nib和故事板在合并冲突中遭受了严重的损失, 代码没有同样的错误. 所有代码都具有语义意义,因此解决冲突并不比通常困难.

反对:原型

在你真正看到一个布局之前,很难弄清楚它是什么样子的. 进一步, 你不能直观地定位视图和控件, 因此,将布局规范转换为有形视图可能需要更长的时间, 而nib和storyboard会给你一个事物如何渲染的即时预览.

反对:重构

重构很久以前编写的代码或其他人编写的代码也变得更加复杂:当元素被定位并使用自定义方法和幻数动画时, 调试会话可能会变得非常困难.

职业:性能

在性能方面, 故事板 和 傲慢的人是 subject to the overhead of loading 和 parsing; 和 in the end, 它们被间接地转换成代码. 不用说,这种情况不会发生在代码生成的ui上.

正方观点:可重用性

任何以编程方式实现的视图都可以以可重用的方式设计. 让我们来看几个用例:

  • 两个或多个视图共享一个共同的行为,但它们略有不同. 一个基类和两个子类很好地解决了这个问题.
  • 一个项目必须被分叉, 目的是创建一个单一的代码库, 而是生成两个(或更多)不同的应用程序, 每个都有特定的自定义.

使用nib和故事板,同样的UI设计过程会复杂得多. 模板文件不允许继承,可能的解决方案仅限于以下几种:

  • 复制NIB和故事板文件. 在那之后,他们的生活就分开了,与原始文件没有任何关系.
  • 用代码覆盖外观和行为, 在简单的情况下,哪一种可能有效, 但可能会导致其他疾病的严重并发症. 代码的重载也会使视觉设计变得无用,并不断演变成令人头疼的问题, e.g., 当某个控件在界面生成器中以一种方式显示时, 但当应用程序运行时,看起来完全不同.

何时使用代码

在iOS用户界面设计中使用自定义代码通常是一个好主意,当你有:

  • 动态布局.
  • 带有效果的视图,如圆角、阴影等.
  • 任何使用nib和故事板是复杂的或不可行的情况.

使用代码

通常,代码生成的ui可以 总是 被使用. 他们很少是个坏主意,所以我要加一个 在这里.

尽管nib和故事板带来了一些优势, 我觉得列出一个列表来阻止代码的使用并没有什么合理的缺点(除了, 也许, 懒惰).

一个项目,多个工具

故事板、nib和代码是构建iOS用户界面的三种不同工具. 我们很幸运能拥有他们. 编程ui的狂热者可能不会考虑另外两个选项:代码让您完成技术上可能的所有事情, 然而,其他选择也有其局限性. 对于其他的开发者来说, Xcode军刀提供了三种工具,可以同时使用, 在同一个项目中, 有效地.

你会问怎么做? 不管你喜欢什么. 以下是一些可行的方法:

  • 将所有相关的屏幕分组到单独的组中, 并使用自己独特的故事板来实现每个组.
  • 在表视图控制器中使用故事板设计不可重用的表格单元格.
  • 在nib中设计可重用的表格单元格,以鼓励重用并避免重复, 而是通过自定义代码加载这些nib.
  • 使用nib设计自定义视图、控件和中间对象.
  • 为高度动态的视图使用代码, 更普遍的是,对于那些不容易通过故事板和nib实现的视图, 同时将视图转换放置在故事板中.

最后,让我们看最后一个将所有内容联系在一起的例子.

一个简单的用例

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

  • 所关注好友的列表(使用可重用的单元格模板,以保持UI在未来列表中的一致性).
  • 配置文件详细信息视图, 组成单独的部分(包括概要信息), 统计数据, 和工具栏).
  • 发送给朋友和从朋友那里收到的消息列表.
  • 一个新的消息表单.
  • 标记云视图,显示用户消息中使用的不同标记, 每个标签的大小与其被使用的次数成正比.

此外,我们希望视图的流程如下:

  • 点击关注好友列表中的一个项目,就会显示相关好友的详细资料.
  • 配置文件详细信息显示了配置文件的名称, address, 统计数据, 最近消息的简短列表, 还有工具栏.

为了实现这款iOS应用,我们的三个UI工具都会派上用场,我们可以使用:

  • 带有四个视图控制器的故事板(列表、细节、消息列表和新消息表单).
  • 用于可重用配置文件列表单元模板的单独NIB文件.
  • 配置文件详细信息视图的三个独立NIB文件, 一个用于组成它的每个单独部分(概要文件详细信息), 统计数据, 最后三条信息), 允许更好的可维护性. 这些nib将被实例化为视图,然后添加到视图控制器中.
  • 标记云视图的自定义代码. 此视图是无法在Interface Builder中设计的视图的典型示例, 既不是通过故事板也不是通过nib. 相反,它完全是通过代码实现的. 为了维持故事板的视觉流, 我们选择向故事板添加一个空视图控制器, 将标记云视图实现为独立视图, 并以编程方式将视图添加到视图控制器. 很明显, 视图也可以在视图控制器中实现,而不是作为一个独立的视图, 但我们把它们分开,以便更好地再利用.

一个真正基本的模型可能是这样的:

这张图展示了一个使用故事板的iOS用户界面设计项目, 傲慢的人,  和自定义iOS代码.

至此,我们概述了一个合理的 复杂的iOS应用程序 谁的核心观点将我们的三个主要方法联系在一起 用户界面设计. 记住:不存在二元决策,因为每种工具都有其优点和缺点.

结束

在本教程中,故事板显著地简化了 iOS UI设计和视觉流程. 的y also eliminate boilerplate code; but all this comes at a price, paid in flexibility. 与此同时,nib通过专注于单个视图提供了更大的灵活性,但没有视觉流. 最灵活的解决方案, 当然, 是代码, 这往往是相当不友好和固有的非视觉.

如果你对这篇文章感兴趣,我强烈推荐你观看 伟大的辩论 来自Ray Wenderlich,花了55分钟讨论nib、故事板和代码制作的u.s..

最后,我想强调一点: 尽量避免使用不合适的iOS UI设计工具. 如果一个视图不能用故事板设计, 或者是否可以用nib或代码以更简单的方式实现它, 使用故事板. 类似地,如果一个视图不能使用nib设计,就不要使用nib. 这些规则虽然简单,但将对你作为开发人员的教育大有帮助.

聘请Toptal这方面的专家.
现在雇佣
安东尼奥·贝洛的头像
安东尼奥·贝罗

位于 Chrzanow、波兰

成员自 2013年5月6日

作者简介

拥有20年以上各种技术经验的多面手, 现在主要关注iOS, 斯威夫特, Objective C和后端

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

专业知识

以前在

斯威夫特lane

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

Toptal开发者

加入总冠军® 社区.