引言
这是xib系列文章的最后一篇,希望这一系列文章能让大家对xib产生“爱恋”。
iOS9中关于xib的一些新特性
之前说过要介绍一下iOS9中有关xib的一些东西。现在简单说一下。我个人认为iOS9与xib相关的东西主要就是UIStackView和storyboard reference的引入。
UIStackView
本来想在这部分好好介绍一下UIStackView的,不过看到网上翻译的一篇文章iOS9:UIStackView入门,(原文:iOS9:Getting Started with UIStackView)瞬间感觉再怎么努力写也不可能写的比人家好了,所以大家可以去看看这篇文章,如果对UIStackView感兴趣的话。还像我一天一点xib:5当xib遇到auto layout中说的那样:
其实普通的UIView也可以作为容器view来管理其subView的约束,我们之前做复杂UI显示逻辑的时候往往也会放一个背景的容器view,stack view就是起到这个作用,意义不是很大,它做的事情UIView也可以做,但是他的优势在于:可以通过设置属性的方式让系统自动添加对其subView的约束。
如果你对UIStackView十分感兴趣,但又无奈仅支持iOS9,那么github上一个开源项目FDStackView可以帮你解决这个问题,你可以在用FDStackView的时候无需考虑低版本兼容的问题,FDStackView自动就帮你解决低版本上的问题了。
是不是感觉到很神奇?如何做到让高版本才出现的类在低版本中也能用的?这不科学啊?对,这的确不科学,它就是一个魔术,关于这个问题我打算写一篇文章来说说,实际上我也写了一个GJAlertController的开源项目,也是解决在低于iOS8中使用UIAlertController的问题。放在了github的GJGroup组中(这是我和同事们成立的一个组,希望大家支持一下里面的项目,都很有意思)。
storyboard reference
先简单介绍一下storyboard reference是干什么用的,iOS开发中是重应用程序、重导航这些概念的,从UINavigationController、UITabBarController的使用中就能看出来,不像Android开发是重Activity,轻应用这些概念。这就导致,我们绝大多数项目都是这样设计的:(通常tabbar常驻底部的是方式一,tabbar随着push消失的是方式二)
无论哪种方式,delegate.windwo.rootController都对应我们的Main.storyboard,就是说如果我们用SB组织项目,所有的VC其实都放在了Main.storyboard中管理,这显然是不好的:
1.SB文件会经常冲突,因为所有VC都在里面,这样不利于团队开发(虽然我们现在能很好的解决SB文件的冲突)。
2.SB管理的VC过于多,不利于修改SB文件,Xcode加载巨大的SB文件的时候有时会出现卡顿
基于这两点,我们有两种解决方法:
1.指定delegate.windwo.rootController的时候不用系统指定,就是说不用Main.storybaord(具体方法之前有说过),而是用代码创建,当代码创建各个tab对应的VC的时候,去加载各自的SB文件,eg:
FirstController *firstVC =
[[UIStoryboard storyboardWithName:@"First" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"FirstController"];
SecondController *secondVC =
[[UIStoryboard storyboardWithName:@"Second" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"SecondController"];
tabVC.viewControllers = @[firstVC, secondVC];
2.如果你感觉上述方法比较low的话,那么storyboard reference来了,它可以不用写代码就能解决这个问题,思路是,一个SB文件中的Segue(带有像扣子一样的线)可以指给一个reference,而一个reference指向另一个SB文件,这样就把集中在SB中的VC分散到了各个SB中去,而Main.storybaord中的segue大多都指向这些reference。
同样网上有一篇iOS9学习系列:Storyboard Reference文章已经写的非常好了,我再怎么写也都是画蛇添足,班门弄斧。
同样的问题来了:如何才能兼容低版本?总不能直接就从iOS9开始吧,答案是:使用RBStoryboardLink
我个人认为苹果是封闭中带有开放的,它把很多好的开源项目的功能或者用户的强烈需求,都在接下来的iOS系统中得到解决了,比如iOS8中应用程序扩展得以实现自定义键盘,iOS9中的storyboard reference、之前没有的Json解析、base64...都陆续的支持了。而Android是开放中带有封闭的,比如Android6.0中的权限管理。
好了,说回RBStoryboardLink,它是在iOS9之前解决上述问题的一个很好的方法,下面具体来说说RBStoryboardLink的用法的,现在从兼容的角度来说,还是RBStoryboardLink来的实在。
RBStoryboardLink
1.新建一个SBDemo工程,创建基于tabbarController的程序,我们这里有两个item:First和Second,并新建First.storyboard和Second.storyboard文件
2.引入RBStoryboardLink。我们这里用pod方式。打开终端进入到工程文件所在文件夹下,执行pod init,这时文件夹中多了一个Podfile文件,打开Podfile文件,编辑:
target 'SBDemo' do
pod 'RBStoryboardLink'
end
执行pod update --no-repo-update,完成后打开SBDemo.xcworkspace
3.分别把Main.storyboard中的Firt、Second的class设置成RBStoryboardLink
4.添加runtime attributes
5.在First.storyboard和Second.storyboard中添加一些控件运行看效果
功能实现了,但是状态栏出了问题了,这是layout的问题,在runtime attributes里加入:
再运行,搞定。
最后的总结
添加runtime attributes的功能我们讲过,但是没有讲添加系统之外的属性,而RBStoryboardLink中添加的就是系统之外的属性,说这个是想让大家知道,xib的学习是很有魅力的,你可以发挥自己的想象力去做事情,大胆的假设,然后去验证,看看xib能不能实现你想要的功能,这些细小的知识点,不一定网上都有,很多东西都是要靠你自己使用然后总结经验,然后发扬光大的。这个过程真的很酷,可能别的程序员写了好多代码,费了好大劲才弄出来的东西,你通过巧用xib轻松的实现了,这是很有成就感的事情,希望大家对此能够有所体会。
在使用xib的时候并不是一帆风顺的,会遇到很多挫折,比如,在xib中用ScrollView就是一件很痛苦的事情,因为系统要通过它的子控件的布局约束来确定自己的contentsize的,而这个过程可能很痛苦,怎么设约束都有问题,说这个不是要说应该怎么解决,而是要说没有什么是一帆风顺的,这九篇文章不能面面俱到的说出一切,我也没有这个能力,在这里就是想尽我所能,让大家对xib产生一点“爱恋”,就可以了。
欢迎大家和我交流沟通,若文章中有错误和纰漏,恳请指正,谢谢。