xib相关(一) —— 基本知识(一)

版本记录

版本号 时间
V1.0 2018.04.11

前言

iOS中的视图加载可以有两种方式,一种是通过xib加载,另外一种就是通过纯代码加载。它们各有优点和好处,xib比较直观简单,代码比较灵活但是看着很多很乱,上一家公司主要风格就是用纯代码,这一家用的就是xib用的比较多。这几篇我们就详细的介绍一个xib相关知识。

认识一下xib

什么是xib?

xib其实就是nib转换过来的,nib 和 XIB 都是Interface Builder的图形界面设计文档。Interface Builder把窗口、菜单栏以及窗口上的各种控件的对象都“冻结”在了一个 nib档里面了,程序运行时,这些对象将会“苏醒”。

nib为二进制文件,XIB为纯文本文件,后者方便版本控制,XIB 可编译为nib


xib的创建和视觉显示

首先我们新建立一个工程,看下图。

xib相关(一) —— 基本知识(一)_第1张图片

这里,点击User Interface 中的View和Empty,就可以建立xib文件,它俩不同的是View是视图,Empty是空的视图。

  • empty里面什么都没有。
  • view默认带一个view视图。

其它的属性,关联方式都一样。


xib与具体类的关联

在说xib之前,我们看一下storyboard,对于新建立的工程系统会自带一个Main.storyboard,这个storyboard会自动的关联到新建立的时候存在的类ViewController,对于类的关联,就是从下图右侧的输入框中输入指定的类名,回车即可,那么这个storyboard就关联到那个类中了。

xib相关(一) —— 基本知识(一)_第2张图片

有人可能要问,为什么要关联啊?这个还是很好理解的吧,你拖进去控件当然要关联指定的类进行处理和显示了。

对于xib同样如此,也是通过下面方式进行关联。

xib相关(一) —— 基本知识(一)_第3张图片

也只有关联后我们才可以将xib中的控件链接到关联的类中作为属性或者触发Action等事件,方便我们进行详细的处理。


xib和storyboard区别

下面看一下xib和storyboard区别。

  • 关联上的区别

    • XIB在创建出来的时候,跟任何文件(类)都没有关系,是一个单独的文件,那么我们在XIB上所拖拉出来的控件。
    • storyboard就像每一个类一样,在创建出来的时候都要指定一个Class来继承一下。
  • 继承上的区别

    • storyboard自带继承关系。
    • XIB在创建出来的时候没有人管,需要我们单独再创建一个类去继承一下才能够管理里面的控件属性。
  • 是否需要主动唤醒

    • 使用storyboard的时候,不需要用代码去告诉程序,可以直接运行(command + R)的方式去展示storyboard中添加好的控制器和控件。
    • xib需要我们主动唤醒,具体主动唤醒后面会和大家说的。

xib加载

下面我们看一下xib加载。

首先我新建立一个xib和对应的view,并将他们进行关联和绑定。

xib相关(一) —— 基本知识(一)_第4张图片

然后将xib设置为红色,方便观看是否加载成功。

xib相关(一) —— 基本知识(一)_第5张图片

然后我们在VC中加入这段代码,就可以正常的唤醒xib了。并将xib的视图加载到当前VC的根View上。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    JJCustomView *customView = [[[NSBundle mainBundle] loadNibNamed:@"JJCustomView" owner:nil options:nil] lastObject];
    customView.frame = self.view.frame;
    [self.view addSubview:customView];
}

这里注意,就是下面这句话可以唤醒xib

JJCustomView *customView = [[[NSBundle mainBundle] loadNibNamed:@"JJCustomView" owner:nil options:nil] lastObject];

这里owneroptions都暂时传递nil,后面会具体进行说明。

我们在xib关联的JJCustomView.m中加入如下代码:

@implementation JJCustomView

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    NSLog(@"2222");
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        NSLog(@"1111");
    }
    return self;
}

@end

下面我们看一下调用栈,这两个方法的调动顺序,其实就是先调用initWithCoder :方法,后调用awakeFromNib方法。

断点打到NSLog(@"1111");这一行,看一下调用栈,如下图所示。

xib相关(一) —— 基本知识(一)_第6张图片

可以看见,加载完Nib那句代码,就调用initWithCoder :方法。

放开断点,在NSLog(@"2222");打上断点,继续看调用栈。

xib相关(一) —— 基本知识(一)_第7张图片

可以看见,这里面调用了一下UINib的类方法。

下面我们看一下frame。

@implementation JJCustomView

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSLog(@"3333 = %@", NSStringFromCGRect(self.view.frame));
}

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    NSLog(@"2222 = %@", NSStringFromCGRect(self.frame));
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        NSLog(@"1111 = %@", NSStringFromCGRect(self.frame));
    }
    return self;
}

看一下输出结果

2018-04-11 23:13:28.523315+0800 JJWebImage[1457:58070] 3333 = {{0, 0}, {414, 736}}
2018-04-11 23:14:06.147699+0800 JJWebImage[1457:58070] 1111 = {{0, 0}, {375, 667}}
2018-04-11 23:14:06.148076+0800 JJWebImage[1457:58070] 2222 = {{0, 0}, {375, 667}}

这里,用的是8plus的模拟器。调用这两个方法的时候并没有改变frame,还是xib的自带的那个frame。

xib相关(一) —— 基本知识(一)_第8张图片

除了上面的NSBundle方式加载xib,还可以通过UINib的方式进行加载。

这里参数bundle参数传递nil,就默认为[NSBundle mainBundle]

// UINib *nib = [UINib nibWithNibName:@"XibView" bundle:[NSBundle mainBundle]];
UINib *nib = [UINib nibWithNibName:@"XibView" bundle:nil];
NSArray *objs = [nib instantiateWithOwner:nil options:nil];
[self.view addSubview:objs[0]];

SB的加载

前面说的是xib的加载,下面我们就看好一下SB的加载。

对于基于UIViewController子类的xib的使用,这种情况下使用很简单,对VC直接alloc,init就可以,VC会自动去找自己对应的xib文件,即使我们自定义了一些init方法,也不需要对加载他的xib做处理,系统会自动帮我们找是否有与其对应的xib文件。

父类会判断有没有和我们这个要初始化的VC相同名字的xib文件,如果有就会加载该xib文件,如果没有,父类就认为我们该VC没有xib文件,就会走正常的init方法。

后记

本篇主要介绍了xib的一些相关的基础知识,感兴趣的给个赞或者关注~~~~

xib相关(一) —— 基本知识(一)_第9张图片

你可能感兴趣的:(xib相关(一) —— 基本知识(一))