凡是维护过中型项目的iOS工程师都应该有过类似的体验: ViewController
代码繁重、功能复杂、维护困难,整个工程寥寥几个 ViewController
就完成了整个项目的开发。每个控制器中都囊括了所有的页面布局、委托代理、网络请求、数据库操作和核心功能,这样的代码往往问题重重,修改起来牵一发而动全身,着实令人头疼。
为了应对这一系列的问题,苹果公司的工程师给我们提供了很多选择去更好的在项目工程中贯彻 MVC
的设计理念,例如使用从前的 Interface Builder
制作 xib
可视布局,现在已经内置到 xcode
里面,并且提供了更为强大 Storyboard
功能,来减少 控制器
中的页面样式布局代码量;再例如 NSFetchedResultsController
这样的类和 CoreData
he UITableViewController
的完美结合,大大减少类似构架项目的代码量,并且稳定高效。
这些技巧在 objc.io 上有一个专门的专题,推荐给大家对应中文站 objc中国 ,感谢objc 中国项目组。
如果放在两年前去讨论iOS工程要不要使用 Stortboard
进行布局,我们可能还会犹豫一下,很多iOS程序猿内心会有一种想把一切化为代码掌控在手中的想法,选择拒绝使用 Storyboard
或者更早的 xib
。但事到如今,iPhone、iPad的屏幕尺寸越来越多,工程里为了适配不同屏幕冗余代码越来越长的时候, Storyboard
似乎成为了我们必须同时也是苹果公司在引导我们将要实践的方向。
从 iOS 6
中的 Autolayout
到 iOS 8
中的 Size Class
,新技术的涌现正是为了应对更复杂的布局任务。有人可能会反驳说,自动布局也可以用纯代码完成呀。你说的没错,纯代码是可以完成,但其复杂程度远远不是重写Frame这么简单了,更灵活地将 Storyboard
和代码结合,才是比较完备的解决方案。
这里通过三个方面介绍通过使用 Storyboard
减小工程代码耦合性的途径:
IBDesignable
和 IBInspectable
Storyboard Preview
NSObject
和 Runtime Attributes
IBDesignable
和 IBInspectable
的出现为 Storyboard
提供了可视化使用高度自定义控件的方法,例子中我们在制作一个双行标签控件,用来显示日期和星期,命名为 DateLabel
,使用方法如下:
objc
//IB_DESIGNABLE 标记 IB_DESIGNABLE @interface DateLabel : UIView //IBInspectable 标记 @property (nonatomic, strong) IBInspectable NSString* dateLabelText; @property (nonatomic, strong) IBInspectable NSString* weekLabelText; @end
其中, IB_DESIGNABLE
标记赋予我们的继承类 DateLabel
可以在界面编辑器里面实时渲染的特权。 IBInspectable
则赋予让界面编辑器可以设置或者预置 View
的参数 dateLabelText
和 weekLabelText
。具体不多介绍了,有点跑题,大家可以参见 如何在iOS 8中使用Swift和Xcode 6制作精美的UI组件 ,同样适用于 Objective-C
和 Swift
。
引用上文介 IBInspectable
支持 Int
, CGFloat
, Double
, String
, Bool
, CGPoint
, CGSize
,
CGRect
, UIColor
, UIImage
等类型的变量。
现在在 Github
上已经有一部分开源的UI控件使用了这项特性,如此一来,很多需要在代码中实现的控件自定义特性,都可以在 Storyboard
中完成,后者的优势也很明显:
ViewController
中的定制 View
代码,减小耦合 Storybord
中提供了预览功能,可以预览其界面在各个尺寸设备上的真实显示效果。详见 Xcode 6中学习Swift、CloudKit 和 Testflight ,搜索 Storyboard Preview
。
大家对这个概念再熟悉不过了,但大家有没有对他作为一个没有界面的控件在 Storyboard
作用产生过疑问呢。先来看下这篇文章 0代码ViewController 的前言。
Storyboard
中的 NSObject
可以是 UITableView
的 DataSource
,也可以是 MapView
的 Delegate
,连线一下,就能将原本在 ViewController
中写得最多的代理方法全部移出,并且,当你需要的时候,这些现成的代理方法,可以直接移到其他的项目中使用。
Runtime Attributes
功能则可以在 Storyboard
中给参数写好初始值,但这里如果控件没有对应的参数的话,则会出现下面的报错。
当你了解了 Storyboard
的基本原理,就会发现 Storyboard
是一个很好用的工具,是 Model-View-Controller
模型中 Controller
跳转逻辑和 View
初始化的实用载体,从根本上把 Controller
中的导航代码移出,把页面配置代码、触摸事件甚至协议委托方法分摊到其他实例中,各个类各司其职,整个项目的逻辑也变的更加清晰、更易维护。