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 方法