内容简介:不同于国外,实际使用例子参见
不同于国外, StoryBoard
从面世到如今饱受国内开发者的质疑,质疑的理由很多,什么不利于多人协作啊,隐藏了UI细节啊,出问题不容易测试,降低执行效率啊等等。此文就是针对这些问题的举例和剖析。
StoryBoard
和 Xib
有什么区别?
StoryBoard
和 Xib
都是用来分离UI样式代码,改善视图代码重用率,增加所见即所得,降低视图测试繁复度的视图系列化工具,
- 其中
Xib
以视图View
为主, -
StoryBoard
以控制器Controller
及其之间的关系,以及和视图View
的关系为主。
实际使用例子参见 《纯Swift项目-Xib | StoryBoard 设备适配技巧》 或其他 StoryBoard
文章
StoryBoard
和 Xib
不利于多人协作, git
合并代码容易冲突,且难以处理?
这个是诋毁 StoryBoard
最多的理由,也是 看上去
最充分的理由。最显著的就是下图这种失败的例子。
在一个 Storyboard
中,大量的 Controller
控制器和 Segue
连线彰显着错综复杂的UI关系,使人望而生畏或者难以维护。
但这并不应该是 Storyboard
的锅,仅仅是使用者对 工具 的滥用!
没错,就是 滥用
,无论是 Storyboard
也好,纯代码也罢,它们的本质都是工具,工具本身没有正义或邪恶,影响工具的是使用者。哪怕是用纯代码开发,如果没有命名规范,肆意的嵌套 if
,不遵守MVC或者MVVM等开发模式,不区分开发环境与生产环境,这样写出来的代码又何谈可维护性,和多人协作呢?
那么反过来说,如何使用 Storyboard
才不算滥用?
避免滥用,最好的方法就是定制规范,就好像代码中的诸多规范一样。每个团队可能有自己不同的喜好,我在此抛砖引玉,列出我们团队使用 Storyboard
的规范,供大家参考。
每个模块独立 Storyboard | 每个 Storyboard 只应该有一个主VC和同页的子VC,主VC不应存在2个以上 |
---|---|
- 一个项目中, Storyboard 不该是孤立存在的,应该像
MVP
模式那样,每个页面都有独立的 Storyboard ,每个 Storyboard 只应该有一个主 VC 和同页的子 VC ,主 VC 不应存在2个以上。(绝大多数情况下,一个 Storyboard 上只应该有一个 VC ) - 页面间的
Segue
连线应该使用Stroyboard Reference Scene
,UITabBarController
的子页因为复杂度应该当成主 VC 处置 - 视图的初始样式应尽量在 Storyboard 上属性面板中设置,非极特殊情况,布局也应在 Storyboard 上使用各种约束配合完成。这样有利于视图样式和视图代码分离,有利于视图代码重用性和兼容性提高。
- 对于逻辑复杂的 VC ,应添加Object对象,并绑定相应的类来分离逻辑代码。
- 对于圆角,背景色,阴影等
CALayer
的样式,应该使用扩展或子类化实例的形式,使用@IBInspectable
属性关键字,在 Storyboard 属性面板中设定初始样式。 - 对于自定义视图,应使用
@IBDesignable
关键字保障在在 Storyboard 上所见即所得!
使用以上原则,只要任务分工合理,基本上不存在多人同时修改同一个 Storyboard
的情况,就算配合失误偶然发生,精简的 Storyboard 其代码量也不大,借助文件比较工具很容易就能处理git冲突。
说到底,臃肿的 Storyboard
和臃肿的 ViewController
一样,都是难以维护且容易 git 冲突的。唯一的解决方案就是有节制的使用工具。
StoryBoard
和 Xib
隐藏了UI细节,且容易导致 ViewController
臃肿?
与其说 StoryBoard
和 Xib
隐藏了UI细节,倒不如说苹果是希望通过他们来引导开发者正确的使用 视图 和 控制器 ,他们创建视图实例的时候都是通过
required init?(coder aDecoder: NSCoder) { } 复制代码
构造方法创建视图实例。所有初始样式都是在属性面板中设置的值,通过
func setValue(_ value: Any?, forUndefinedKey key: String) { ...... } 复制代码
来赋值给视图对应的属性。
至于说导致 ViewController
臃肿,更是荒谬, StoryBoard
提供了多种方案来分离代码,只不过很多人不知道而已。
拿美团的主页UI举例
这样的首页较为复杂,正常布局的话需要多个 CollectionView
和一个 UITableView
如果这些视图的 Delegate
都由 ViewController
来实现,自然显得臃肿且混乱。
一般手写派会分出3个 ChildViewController
来解决臃肿问题,难道 Storyboard
就做不到么?
答案是否定的,很早的版本,苹果就给出了上图中的解决方案。一个占位的容器视图指向子控制器的 Embed Segue
按住 Control
键连线到想要包含的子控制器,占位视图的实例==子控制器的 view
(子控制器根视图)
选择 Embed
连线方式后,子控制器 的尺寸变化成跟占位视图一样的尺寸
这样我们可以将功能图标的 CollectionView
的代码放到这第一个子控制器上, CollectionViewDelegate
、 CollectionViewDataSource
等代码也由子控制器实现
同理,优惠专区可以再添加一个 Container View
,指向第二个子控制器。
通过 Container View
创建的 ChildViewController
如何与主 ViewController
传参或互相调用?
ChildViewController
可以通过 self.parent(Swift)|| self.parentViewController(OC)来拿到主 ViewController
的实例。 主 ViewController
可以通过 self.chilren(Swift) || self.childViewControllers(OC)来拿到 ChildViewController
的实例,它是一个数组,顺序等同于占位视图再视图层次中的顺序。
值得一提的是,通过此种方式创建的 ChildViewController
,其构造方法晚于主 ViewController
,但生命周期中的 viewDidLoad
则早于主 ViewController
, 因此在 ChildViewController
中的 viewDidLoad
方法中, self.parent 是 nil
,这时不能拿到主 ViewController
实例。如果需要在初始化的时候拿到主 ViewController
的实例,则应该在主 ViewController``viewDidLoad
方法中,调用 ChildViewController
的特定方法,把 self 当参数传过去。
- 除此之外还可以使用Object对象
将它添加到控制器之上。
它的本质是一个继承自NSObject的子类,我们完全可以把它当成一个小功能模块的控制器。
class FeaturesController: NSObject, UICollectionViewDataSource, UICollectionViewDelegate { @IBOutlet weak var collectionView:UICollectionView! func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { <#code#> } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { <#code#> } } 复制代码
在 Storyboard
上选中这个 Object
,绑定上面的类
Object
,在弹出的菜单中连线
右键 CollectionView
设置 Delegate 和 DataSource 等的连线
在主 ViewController
中如需调用这个模块的方法或者传参
class HomeController: UIViewController { @IBOutlet weak var featuresController:FeaturesController! override func viewDidLoad() { super.viewDidLoad() featuresController.datas = [....] featuresController.collectionView.reloadData() } } 复制代码
完成连线,同理,如果一个页面需要多个子模块,可以在 Storyboard
上拖入多个 Object
,并绑定不同的模块控制类,相对于占位的 Container View
和 ChildViewController
方法, Object
方法在传参或互相调用方面,更加简便。缺点是没有 ChildViewController
的生命周期方法,如需使用 viewWillAppear
等,需要在主 ViewController
的 viewWillAppear
中,调用 Object
的自定义方法。
通过上面的2种方法不难看出,并非是 Storyboard
造成 ViewController
代码臃肿,而是因为设计不当导致,就算你不用 Storyboard
,把所有功能都写在一个 ViewController
里一样臃肿。这都是使用者决定的,并非 Storyboard
的责任!
StoryBoard
和 Xib
出了问题不容易测试?
这个问题其实问的很模糊,我也是咨询了很多人才知道,他们所谓的问题不容易测试,是指如下两种情况:
- 修改或删除 @IBOutlet 的变量名时,对应的
Storyboard
上未做处理,导致运行时崩溃,崩溃内容看不懂!
StoryBoard
和 Xib
降低执行效率?
(未完待续。。。。)
以上所述就是小编给大家介绍的《纯Swift项目-Xib | StoryBoard 多人协作技巧》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Git多人协作
- GitHub分支管理 - 多人协作
- Git bug分支与多人协作
- web 项目如何进行 git 多人协作开发
- GitLab 9.2 发布,简化多人协作&增强本地化
- 前端数据模型Model,适用于多人团队协作的开发模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。