init,initialize,initWithCoder:,initWithFrame:各方法的区别和加载顺序

1、先把OC的类分清楚各有什么方法
• 普通类的方法
init
initialize:
• 控制器类的方法
init
initialize:
initWithCoder:
• UI控件类的方法
init
initialize: 当类第一次接受到消息时调用一次
initWithCoder: 从文件中加载UIView时执行
awakeFromNib:从xib、storyboard中创建时会调用
initWithFrame:代码创建时,会执行此函数
2、init方法
每个类被创建的时候就会调用init方法

Person *p1 = [[Person alloc]init];
Person *p2 = [[Person alloc]init];
Person *p3 = [[Person alloc]init];
Person *p4 = [[Person alloc]init];

打印信息

2015-10-14 10:42:58.852 afgasdgsdfsd[856:19063] Person---init---Person
2015-10-14 10:42:58.852 afgasdgsdfsd[856:19063] Person---init---Person
2015-10-14 10:42:58.853 afgasdgsdfsd[856:19063] Person---init---Person
2015-10-14 10:42:58.853 afgasdgsdfsd[856:19063] Person---init---Person

——-在有继承关系的情况下,比如Student类继承Person类,那么在不重写子类的init方法时,创建子类对象

Person *p1 = [[Person alloc]init];
Person *p2 = [[Person alloc]init];
Person *p3 = [[Person alloc]init];
Person *p4 = [[Person alloc]init];
Student *s = [[Student alloc] init];


- (instancetype)init{

    if (self = [super init]) {
        NSLog(@"Person---init---%@",[self class]);
    }
    return self;
}
打印信息
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Student

我们可以看到再一次调用了父类的init,因为父类帮子类创建了对象。
如果子类重写了init方法,也会先调用父类的init。
3、initialize:
这个类跟init经常混淆,但是还是有区别的,我们先看看调用的顺序

#import "Person.h"

@implementation Person
- (instancetype)init{

    if (self = [super init]) {
        NSLog(@"Person---init---%@",[self class]);
    }
    return self;
}

+ (void)initialize{

    if ( self == [Person class]) {
        NSLog(@"Person----initialize---%@",[self class]);
    }
}
@end
打印信息
2015-10-14 11:00:43.568 afgasdgsdfsd[904:22876] Person----initialize---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person
2015-10-14 11:00:43.569 afgasdgsdfsd[904:22876] Person---init---Person

我们可以看到先打印initialize:方法,而且只打印的一次,为什么呢?
在程序运行过程中,它会在你程序中每个类调用一次initialize。这个调用的时间发生在你的类接收到消息之前,但是在它的超类接收到initialize之后。
系统在第一次使用这个类的时候调用(一个类只会调用一次)
如果在有继承关系的情况下有三种
一、父类重写:只有父类调用
二、子类重写:只有子类调用
三、父子类重写:父子类调用

#import "Person.h"

@implementation Person
- (instancetype)init{

    if (self = [super init]) {
        NSLog(@"Person---init---%@",[self class]);
    }
    return self;
}

+ (void)initialize{

    if ( self == [Person class]) {
        NSLog(@"Person----initialize---%@",[self class]);
    }
}
@end

#import "Student.h"

@implementation Student

- (instancetype)init{

    if (self = [super init]) {
        NSLog(@"Student---init");
    }
    return self;
}


+ (void)initialize{

    if ( self == [Student class]) {
        NSLog(@"Student----initialize---%@",[self class]);
    }
}
@end
Person *p1 = [[Person alloc]init];
    Person *p2 = [[Person alloc]init];

    Student *s = [[Student alloc] init];
2015-10-14 11:17:54.500 afgasdgsdfsd[970:26330] Person----initialize---Person
2015-10-14 11:17:54.501 afgasdgsdfsd[970:26330] Person---init---Person
2015-10-14 11:17:54.501 afgasdgsdfsd[970:26330] Person---init---Person
2015-10-14 11:17:54.501 afgasdgsdfsd[970:26330] Student----initialize---Student
2015-10-14 11:17:54.502 afgasdgsdfsd[970:26330] Person---init---Student
2015-10-14 11:17:54.502 afgasdgsdfsd[970:26330] Student---init

4、initWithCoder: 作用:通过xib或者storyboard创建UI控件就会调用这个方法

这个方法时遵守了NSCoding协议 , NSCoding协议声明了两个方法,一个类必须实现,因此这类的实例可以编码和解码。符合面向对象的设计原则,一个物体被编码或解码负责编码和解码实例变量。这样做的一个编码器指示对象通过调用encodeWithCoder:或initWithCoder:。encodeWithCoder:指示对象实例变量提供的编码器,编码一个对象可以接收这个方法任意次数。initWithCoder:指示对象初始化本身从编码器提供的数据;因此,它将取代任何其他初始化方法和每个对象只发送一次。任何对象类,应该codable必须采用NSCoding协议和实现它的方法。

/**
 *  从文件中解析一个对象的时候就会调用这个方法
 *  通过xib或者storyboard创建UI控件就会调用这个方法
 */
- (id)initWithCoder:(NSCoder *)decoder
{
    if (self = [super initWithCoder:decoder]) {
        // 代码
    }
    return self;
}

要编码的对象,必须实现NSCoding协议。
@protocol NSCoding
-(void) encoderWithCoder:(NSCoder *) aCoder;
-(id) initWithCoder:(NSCoder *) aDecoder;
@end
当对象需要保存自身时-encoderWithCoder:方法被调用
当对象需要加载自身时-initWithCoder:方法被调用
5、initWithFrame: 通过代码创建,那么就会调用这个方法
如果是通过代码创建,那么就会调用这个方法,进行frame的部署,还有控件的创建。但是在这个方法中创建控件并且设置尺寸的话,你会发现UI控件不会显示。为什么呢?因为initWithFrame:调用时,frame是0,没有尺寸的,所以根据这个frame设置UI控件的frame自然也为空。一般在这个方法中初始化UI控件。在layoutSubviews方法设置UI控件的frame。

/**
 *  通过代码创建控件的时候就会调用
 */
- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        // 初始化UI控件
    }
    return self;
}
/**
 *  UI控件重新部署
 */
- (void)layoutSubviews{

    [super layoutSubviews];
    // 设置UI控件的frame
}

例子—创建一个vc,在storyboard上关联界面,在界面上新增一个view,关联我们的自定义view:XibShow。
执行顺序:
1、在viewDidLoad之前,由于是storyboard上创建的类,会先执行好,且会顺序走 initWithCoder、awakeFromNib两个方法
2、到viewDidLoad之后,执行到用代码创建的view,只会走 initWithFrame 方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值