type
Post
status
Published
date
Feb 22, 2016
slug
summary
tags
iOS
category
技术分享
icon
password
在项目中有些 view 需要独立做成一个组件,供多个 VC 使用,而且本人项目中习惯使用 XIB,所以这个 view 的组件也希望使用 XIB 来实现。但是当我们创建 UIView 的时候默认是不包含 XIB 文件的,这就需要再创建一个同名的 XIB 文件。但是如何把 XIB 和 UIview 关联起来呢。
通常我们通过代码加载 XIB 的方法是:
+(id)viewFromNibNamed:(NSString*)nibName owner:(id)owner{ NSArray* nibView = [[NSBundle mainBundle] loadNibNamed:nibName owner:owner options:nil]; return [nibView firstObject]; }
注意到上面有一个 owner 属相,这个属性就是表明这个 view 文件的所有者,通常对应一个 VC。
单纯的创建 view 类和同名的 XIB 是没有效果的,接下来要做的就是把 XIB 和对应的 view 类关联起来
关联有两种方式,假设自定义的的UIView子类为TestView,三个文件分别为:
TestView.h
TestView.m
TestView.xib
XIB 中的 UIView 控件与类关联

通过XIB加载UIView-1
这种方式就是设置 XIB 中 view 的 custom class 为TestView。
使用方式为
NSArray* nibView = [[NSBundle mainBundle] loadNibNamed:@"TestView" owner:nil options:nil]; TestView *testView = [nibView firstObject]; [self.view addSubview:testView];
这种方式会通过
initWithCoder:
方法来从 XIB 文件初始化该 view。使用的时候我们可以通过 awakeFromNib
方法来做进一步处理。通过这种方式需要注意的是在
initWithCoder:
方法中,并没有建立 XIB 和 TestView 的 IBOutlet 连接,所以在这里通过代码引用 XIB 中的控件是引用不到的,而当awakeFromNib
执行的时候,各种 IBOutlet 都连接好了。所以如果有子控件的初始化工作,最好放在awakeFromNib
里面。通过 File’s owner 来关联

通过XIB加载UIView-2
这种方式是设置 XIB 中的 File’s owner 为TestView。
这种方式创建 view 需要手动来初始化
- (instancetype)initFromNibWithFrame:(CGRect)frame owner:(id)owner{ owner = owner ?: self; UIView *nibView = [UIView viewFromNibNamed:NSStringFromClass([self class]) owner:owner]; if (!nibView) return nil; nibView.frame = frame; self = [super initWithFrame:nibView.frame]; [self addSubview:nibView]; [self nib_viewDidLoad]; return self; }
初始化可以在自定义的
nib_viewDidLoad
里面进行,这个时候 XIB 和 TestView 的 IBOutlet 连接也已经建立好了由于XIB没有设置 view 的 custom class 所以并不会执行
initWithCoder:
和awakeFromNib
方法。缺点
上面两种方式都可以实现通过代码加载 XIB 的目的。
但是有一种情况就是我们的 viewController 也使用 XIB 来布局的,这个时候如果我们拖拽一个 view 在 VC 的 XIB 中,然后设置这个 View 的 custom class 为 TestView 时,上面的方法就无效了。因为虽然同样是 TestView ,但是加载布局文件不同,这里所加载的布局文件是 VC 所在 XIB 的布局文件。
另外,XIB 中的 file’s owner 其实也就类似是传统 MVC 中的 controller 的角色,因此其最好是 UIVIew,NSObject,UIViewController 这样的类。