如何优雅的使用xib进行开发

IB 和纯代码布局在 iOS 界一直都存在着不小的争论,唐巧也曾专门撰文来对比二者。网上也能找打一大堆关于 IB 或者纯代码好的或者不好的文章。即使是大神对这个也有着不一样的看法。 Sunny 力挺 IB 开发,据说Ibireme YY大神是纯代码的拥簇,虽然两位大神现在也不会再写 UI 了…

最近实在是比较忙,先是公司从成都搬到了重庆,纠结了半天还是决定留在现在的团队,再继续往前走下去。再是到重庆没有完整的办公场地的情况下,启动了2.0计划。好在坚持了一段时间之后,2.0版本已经完成了95%的开发等着接下来的优化了。停止可这么长时间的博客,终于也想起来了要打理打理。

在项目中一直都坚持着使用xib来进行界面布局,除了一些界面需要使用静态单元格用了StoryBoard其他的view层全部使用了xib进行。即使这样,刚刚看了一下也有了16w+行代码,这篇文章就算是一些心得吧。

正文

xib的构成

随便拿了一个xib文件,我们总是能看到这样的内容:

  • File’s Owner
  • First Responder
  • View (虽然我们看到的是FooCell)

其实这就是xib就是由这三部分构成的。

File’s Owner

首先我们先聊聊File's Owner。我们使用xib定义的所有都是对应MVC架构中的View层(使用StoryBoard定义的controller实际上定义的也是这个controller的self.view)。这就很显然了,这里的File's Owner其实就是连接View 和ViewController的桥梁。其实File’s Owner就是Custom Class类型的对象,而xib中的其他元素都是该对象的成员变量,但是需要手动来关联Custom Class中的成员变量与xib中对象之间的关系。举一个简单的例子,我们在创建vc的时候勾选了also create XIB file,这时候创建的xib他的File's Owner就能看到class就是这个VC的class,这时候对应的tableview textfiled等控件的delegate 和datasource都可以通过连线到File's Owner中实现。

First Responder

再来说说First Responder。首先请想象一下,我们在使用textfield的时候是不是经常会用到becomeFirstResponderresignFirstResponder两个方法,所以,很容易理解First Responder就是在这个xib中正在与用户交互的那个控件。

View

最后一个就更简单了。以至于我都不知道怎么样来更仔细的介绍了。反正我们这个xib我们看到的部分就是view 我们放的控件也全部都是放在这个view中的。

在xib中定于圆角等layer的属性

相信很多人都知道怎么样给xib上的属性定义圆角,也就是在右边工具栏选中第三个的User Defined RunTime Attributes中设置layer.borderRadius。 然是如果我们要设置颜色呢?这这个地方我们需要的CGColor但是这里只有一个UIColor对象。

在这里我使用到了一个category,并在实现文件中写下了这个方法

1
2
3
- (void)setBorderColorWithUIColor:(UIColor *)color {
self.borderColor = color.CGColor;
}

这样在设置bordercolor的时候就可以设置keypath为borderColorWithUIColor并且使用UIColor来赋值了。很简单的tip 由于我比较懒,如果能够通过xib绝对不愿意在代码中写,所以这个对我来说还是很有用的。

IBInspectable

这个是方便我们在xib文件中通过右边的工具栏给view添加一些属性的,比如

1
2
3
4
5
@interface FooView ()
@property (assign, nonatomic) IBInspectable CGFloat borderWidth;
@property (strong, nonatomic) IBInspectable UIColor *borderColor;
@property (assign, nonatomic) IBInspectable CGFloat cornerRadius;
@end

这个时候在xib的右边工具栏中就会出现这样的东西

这时候只需要给对应的属性写上对应的setter方法就ok了。

IB_DESIGNABLE

这个就比较牛逼了,因为我们平常要是自定义了一个View的话,如果把这个View放在其他的xib中,这时候他其实是看不到她的效果的。这个可能会让我们感觉到很痛苦,这样的话就完全不符合XIB的核心思想所见即所得

不说闲话了直接进入主题IB_DESIGNABLE

我们在自定义View的@implementation前面写上IB_DESIGNABLE

1
2
IB_DESIGNABLE
@implementation FooView

然后在这个view的drawrect方法里面写下一些代码。然后把这个view拖到其他的xib中,就会看到一些神奇的东西。

需要注意的是,这个情况下代码只是在drawrect方法中有效。

但是如果我们把IBInspectableIB_DESIGNABLE结合起来呢?

IBInspectable && IB_DESIGNABLE

INInspectable那一节的代码中在FooView.m中的@interface的前面写上IB_DESIGNABLE然后我们再在看看xib

1
2
3
4
5
6
IB_DESIGNABLE
@interface FooView ()
@property (assign, nonatomic) IBInspectable CGFloat borderWidth;
@property (strong, nonatomic) IBInspectable UIColor *borderColor;
@property (assign, nonatomic) IBInspectable CGFloat cornerRadius;
@end

就出现了神器的效果

所见即所得!!!

IBOutletCollection(ClassName):

这个关键字支持创建一个IBOutlet控件的数组,

就是这样,顺序的话测试下来应该是按照脱线顺序来的。针对这个特性,确实不知道应该怎么使用。目前为止也还没有找到合适的应用场景。

小tip

tip1

其实在使用xib的时候还没踩到过什么大的坑,就只是遇到过一次由于没有理解到File‘s Owner的涵义。

在使用xib自定义一个view的时候每次使用到这个view总是会crash,并且报错,

1
'NSUnknownKeyException', reason: … this class is not key value coding-compliant for the key X

多次删掉所有的连线然后重新拉线,多次clean,也无法解决,后来才发现File‘s Owner 错了,改成NSObject之后就好了。

最尴尬的事情是,笔者在写这篇文章的时候,修改回去又是正常的了。所以如果出现这种问题,首先检查是不是拉线冲突,如果无法解决的话,就试试修改File's Owner吧!

tip2

使用

1
[[NSBundle mainBundle] loadNibNamed:@"TestView" owner:self options:nil][0];

来创建由xib定义的view。如果直接alloc init创建出来的view 如果有block等其他的回调的话,是很麻烦的事情。这个真的可以去试试。

结束的话

关于AutoLayout什么的实在没什么说的,感觉已经用烂了,无论是用代码布局的时候使用Masonry还是现在使用了xib,实在想不到有什么好介绍的。

非常遗憾的是IBInspectable并不能修饰UIKit下的控件,所以,我还是没有找到一个很好的方法让拖出来的控件能够实时的展示。

CepheusSun wechat
订阅我的公众号,每次更新我都不一定会告诉你!
坚持原创技术分享,您的支持将鼓励我继续创作!
0%