IOS入门之StoryBoard

时间:2022-04-27
本文章向大家介绍IOS入门之StoryBoard,主要内容包括概述、XIB、StoryBoard、StoryBoard本质、StoryBoard使用、Storyboard 使用规范、Storyboard 命名规范、Storyboard 界面规范、布局规范、初学StoryBoard的一些bug、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

概述

在iOS的发展历程中,IOS开发经历了三种主要流派:使用代码手写UI及布局;使用单个xib文件组织viewController或者view;使用StoryBoard来通过单个或很少的几个文件构建全部UI。而在最近几年的开发中,苹果对 Storyboard 的开发力度也不断增强,添加了更多功能和特性,大大方便了界面的开发、适配以及提升代码性能。

我们来看看三种方式的主要区别:

手写页面和逻辑代码

如果你的目的是写一些可以高度重用的控件提供给其他开发者使用,那毫无疑问最好的选择应该是使用代码来完成UIView的子类.这样进一步的修改和其他开发者在使用时,都会方便不少.使用代码也是最为强大的,会有xib或者StoryBoard做不了的事情,但是使用代码最终一定能够完成所要的需求。

XIB

其实IB和xib是从iOS SDK初次面世开始就是捆绑在开发者工具套装内的内容了,而到了Xcode 4之后更被直接集成到了Xcode中成为了IDE的一部分. xib设计的一大目的其实是为了良好的MVC:一般来说,单个的xib文件对应一个ViewController,而对于一些自定义的view,往往也会使用单个xib并从main bundle进行加载的方式来载入.IB帮助完成view的创建,布局和与file owner的关系映射等一些列工作。

但是xib最大的问题在于xib中的设置往往并非最终设置,在代码中你将有机会覆盖你在xib文件中进行的UI设计.在不同的地方对同一个属性进行设置,这在之后的维护中将会是噩梦般的存在.因为其实IB还是有所局限的,它没有逻辑判断,也很难在运行时进行配置。

StoryBoard

简单理解来说,可以把StoryBoard看做是一组viewController对应的xib,以及它们之间的转换方式的集合.在StoryBoard中不仅可以看到每个ViewController的布局样式,也可以明确地知道各个ViewController之间的转换关系。 现在StoryBoard面临的最大问题就是多人协作.因为所有的UI都定义在一个文件中,因此很多开发者个人或企业的技术负责人认为StoryBoard是无法进行协作开发的,其实这更多的是一种对StoryBoard的陌生所造成的误解.虽然Apple并没有在WWDC明确提及,但是没有人规定整个项目只能有一个StoryBoard文件。 现在会有一些对于StoryBoard性能上的担忧. 因为相对于单个xib来说,StoryBoard文件往往更大,加载速度也相应变慢。不过苹果正在这方面做大的改进。

StoryBoard本质

StoryBoard 的本质是一个 XML 文件,描述了若干窗体、组件、Auto Layout 约束等关键信息。示例文件 https://github.com/johnlui/AutoLayout/blob/master/AutoLayout/Base.lproj/Main.storyboard Storyboard 最大的好处就是把界面和代码分离,如同 Web 开发中 CSS 描述界面,HTML 描述内容,JavaScript 描述行为一样,能让代码变得更清晰易读,界面的行为以及相互的逻辑也变得更直观。

使用 StoryBoard 的 iOS 项目均以初始化 StoryBoard 文件作为整个程序的初始化入口,UIViewController 类是由于被 StoryBoard 绑定而初始化,从而启动app并运行。

StoryBoard使用

1,在ARC下创建StoryBoard文件

2,一般情况下, 程序都是写在Xcode默认的Main.storyboard里面,也可以自定义storyboard到相应的模块。

3,创建自定义StoryBoard后, 记得要修改Main Interface为自己定义的StoryBoard

注:大家记得主界面这里Is Initial View Controller要记得勾选, 这样红圈里面的小箭头才会出现, 表示程序运行从这个界面开始。

Storyboard下Xcode右下角, 大家在下方Filter搜索栏可搜索自己想要添加的控件类型, 并拖拽至屏幕中央的View Controller上。这和其他的界面开发软件都差不多。

当然也可以对控件的属性进行编辑。

我想看到这里大家都不禁想跃跃欲试了吧。入门教程就讲到这里,接下来说说如何写一套代码和页面分离的ios高质量代码规范。

Storyboard 使用规范

Storyboard 分离规范

除非是单页面应用,在大多数情况下,使用单一 Storyboard 往往是不可行的,因为每个 App 通常由各种不一样的复杂模块构成,每当里面的一个元素的属性或位置产生变化,都会导致整个 Storyboard 文件产生多处代码的变动。尤其在 Git 代码版本的控制下,处理分支合并产生的冲突会变得非常麻烦。

所以,把 Storyboard 分离有一个 1 - 5 原则:把每一个 Storyboard 尽量分离成一个人处理范围,每一个 Storyboard 尽量控制少于 5 个 View。例如,设置页面、注册页面、信息详情页、发布页面等,基本上只需要一人就能负责,而且页面大多数情况下都会少于 5 个 View (如果超过 5 个的时候,就可以考虑是不是在里面可以考虑把它们再分离)。把该模块的所有 View 都放在同一个的 Storyboard 文件里进行管理。这样就能大大减少相互冲突的情况,并且 Storyboard 的读取和渲染性能也比单独打开一个大型 Storyboard 的要快不少。

比如我们把项目的Storyboard 全部放在一个文件维护。

Storyboard 命名规范

一套优秀的代码项目,变量的命名,代码的语言风格都会有一套对应的规范,以便于成员之间进行沟通和开发。在 Storyboard 里面,各种的元素标识同样地也需要一套命名的规范,以便于开发之间的沟通。。例如:albumCollectionViewController -> Album Collection View Controller,passwordLabel -> Password Label。这个可以根据各个团队和行业的规范自己作一个命名规范。

Storyboard 界面规范

Storyboard 除了作为 UI 界面的构建语言之外,还担当着界面预览的角色。界面规范有一个原则,就是当把 Storyboard 展示给其他人的时候,尽量做到能让别人一看就知道这个 Storyboard 是干什么的,界面之间的逻辑是怎样的,界面大致的效果是如何的。

布局规范

Xcode 本身就有就有布局辅助线提示的功能,当进行拖动的时候,可以根据提示的辅助线来进行 View 或控件之间的对齐,合理利用此特性能方便我们调整出整齐的布局。

View 和 View 之间的摆放,可以遵循从左往右,从上到下的原则,进行逻辑排列。因为在 Storyboard 里 View 之间的连线算法都是从 View 的右边缘出发,到另外一个 View 的左边缘结束,如果调转了,就会出现很多交叉的连线,让界面看起来很乱。

在 Xcode 7 里,新增加了 Storyboard Reference 控件(虽然是在 iOS 9 新增加的,但 iOS 8 也可用)。合理使用此控件,能让 Storyboard 描述出 View 与其它 Storyboard 的跳转逻辑。并且可以通过 Segue 来进行 View 之间的数据传递,统一规范 View 之间跳转的代码,让逻辑更清晰。

所以我们在写布局的时候尽量预览下实际效果。

初学StoryBoard的一些bug

问题1

初学 iOS 开发的时候,如果使用了 StoryBoard,大家可能遇到过这个奇怪的 bug,比如页面全黑。 APP 在启动以后,会先启动主 StoryBoard,这时候一定要记得主勾选Is Initial View Controller这个选项。

问题2

如果我们在写多个StoryBoard的时候,对于初学者经常回初学下面的情况。

这个警告的意思是,这个窗体没有入口,无法被触达。解决方式有两种: 1,设置为该 StoryBoard 的初始窗体:

给该窗体设置一个 StoryBoard ID:

然后我们就可以在代码中写跳转逻辑了。 主界面

let vc = UIStoryboard(name: "Second", bundle: nil).instantiateInitialViewController() as! UIViewController
self.navigationController?.pushViewController(vc, animated: true)

第二界面

let vc = UIStoryboard(name: "Second", bundle: nil).instantiateViewControllerWithIdentifier("First") as! UIViewController
self.navigationController?.pushViewController(vc, animated: true)

当然,也可以用 self.presentViewController 调用他们。