xib文件有以下几个重要的属性:
xib文件名
File’s Owner
xib文件中的视图的Class
xib文件中的视图的Outlet指向
File’s Owner 可以关联到某类,然后通过IBOutlet 可以提供视图中各种逻辑
自定义视图类,xib中设置布局,类中实现逻辑
纯代码实现
Xib文件
File’s Owner为nil的xib
新建BlueView.xib, 由于它会放到其它View上作为subview,所以这儿size是Freeform, Status Bar是:None
完成布局:
结论:
File’s Owner为nil的xib文件中的视图属于通用视图,在工程中可以复用
从xib加载进来的View在父视图中的位置是不确定的,因此需要开发者自行指定
视图中的所有子视图会被原封不动地Load进来
File’s Owner为self的xib
以与上例相同的方式创建GreenView.xib
加载File’s Owner为self的 view当然也可以用上一例的方法,但也可以更简单
结论:
File’s Owner不为nil的xib文件中的视图属于专用视图,在工程中不应该被复用
只要self主动调用loadNibNamed方法,self持有的IBOutlet指向的视图就会被初始化
存取xib中的视图用不着views[0]的方式,可以通过IBOutlet类型的property进行存取
File’s Owner为特定类的xib
原理与上面3说的一样的,只不过这儿我们特别定义一个NSObject的子类来作为xib的Owner, 要所有需要关系的view都可以声明在这个Owner中,这样方便代码管理与维护。
结论:
File’s Owner类可以封装视图中的各种逻辑,而不仅仅是提供视图内容
只要通过File’s Owner类主动调用loadNibNamed方法,该IBOutlet指向的视图就会被初始化
加载xib中文件名和视图类名一致的视图
在UIView的子类中通过IBOutlet提供下级xib的逻辑
通过UIViewController的initWithNibName:bundle:方法加载xib文件中的视图
initWithNibName方法与 initWithNibName方法的对比
右键点击"Files's Owner", 里面有个默认的IBOutlet变量view, 看一下后面有没有做关联,如果没有就用左键拉到下面的View和视图做个关联
这样在initWithNibName时会自动修改view的值,否则会因为view没值而报错
结论:
将xib的File’s Owner设成一个UIViewController子类,可以将这个xib文件的视图展示和外部响应事件(例如点击一个按钮触发的点击事件,该视图的手势事件等)全部封装在一个View Controller中,如果把按钮的点击事件封装在一个UIView类中,貌似破坏了MVC模式,因此最好将xib的File’s Owner设成一个UIViewController子类,该类可以通过addChildViewController方法将其添加到现有的View Controller上。如果只是希望加载视图,可以通过viewcontroller.view存取。
通过UIViewController+NIB加载xib文件中的View Controller类和其视图
如果希望ViewController A加载并响应a XIBView中的按钮点击事件,这时必须建立一个a XIBView到ViewController A的IBAction,如果ViewController A需要拥有多个这样的XIB,那么ViewController A会变得非常的庞大,此时可以通过为每一个XIB设置一个ViewController,再让ViewController A加载这些Child View Controllers,这样可以将这些事件的响应职责和视图的描绘工作分派给专门的Child View Controller,在减小ViewController A体积的同时,也可以提高各个xib的可复用性。
总结
通用的xib
- 如果xib只是单纯的界面展示,那么File’s Owner可以随意。
- 如果xib中包含了按钮、手势等用户输入事件,那么File’s Owner最好设置为UIViewController类的子类。
补充:
NSBundle.mainBundle().loadNibNamed("RedView", owner: redViewOwner, options: nil) 返回的是一个数组
因为xib中可以有多个视图控件,从xib中load出来的views数组中视图对象的排列顺序和xib scene中的对象排列顺序一致(其实就是xml文件中元素的排序而已)
在写界面时同时混用xib和代码可以提高效率,而对xib的使用主要体现在其专用性和通用性上。
- 对于一些专门的界面,例如App中的设置界面,纯代码写难免会浪费时间,此时可以通过xib文件的拖控件方法来定制。这个xib是专用于某一个界面的,目的是提高效率。
- 对于一些通用的控件甚至界面,例如一个很漂亮但实现起来非常复杂的按钮,此时可以通过load xib文件中的视图来快速添加。这个xib对于所有视图是共用的,目的是提高可复用性。
- 同时也可以混搭使用故事版,因为故事板可以方便地管理页面,如果几个页面间的关系很稳定,不会乱跳转的话,可以部分地使用故事版,然后在代码中调用故事版就是了
代码手写UI
优点:
可以专注于编码环境
版本管理时的优势,检查追踪改动以及进行代码合并相对容易一些
代码重用性,优化
缺点:
不到运行时大家都不知道会是什么样子
开发速度慢。相比可视化的IB来说,代码量大量增多,也就更容易出现bug
维护时代码定位和寻找相对不方便
可视化布局(xib,StoryBoard)
优缺点略
可以把StoryBoard看做是一组viewController对应的xib,以及它们之间的转换方式的集合。
最大的优势就是一般可以加快速度,特别事自动布局优势明显
技巧:
1. 在一组view层次中进行选择
按住Cmd和Shift,然后在需要选择的view上方按右键,就可以列出在点击位置上所有的view的列表
从xib中加载view的执行步骤
先调用init(coder aDecoder: NSCoder)(从xml文件中加载view),
之后调用awakeFromNib()(当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作),
然后是layoutSubviews()(只有在这里frame的值才是正确的值,所以从xib中加载view时,前两个方法里只适合创建下级view对象,只有在本方法里才能去定位下级view)