OC--init,initialize,initWithCoder:,initWithFrame:各方法的区别和加载顺序
1、先把OC的类分清楚各有什么方法
- 普通类的方法
init
initialize: - 控制器类的方法
init
initialize:
initWithCoder: - UI控件类的方法
init
initialize:
initWithCoder:
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
#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
Alex 2015/10/14 11:17:25
#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]);
}
}
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:
这个方法时遵守了NSCoding协议
苹果官方的解释是:
The NSCoding protocol declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).
In keeping with object-oriented design principles, an object being encoded or decoded is responsible for encoding and decoding its instance variables. A coder instructs the object to do so by invoking encodeWithCoder: or initWithCoder:. encodeWithCoder: instructs the object to encode its instance variables to the coder provided; an object can receive this method any number of times. initWithCoder: instructs the object to initialize itself from data in the coder provided; as such, it replaces any other initialization method and is sent only once per object. Any object class that should be codable must adopt the NSCoding protocol and implement its methods.
It is important to consider the possible types of archiving that a coder supports. On OS X version 10.2 and later, keyed archiving is preferred. You may, however, need to support classic archiving. For details, see Archives and Serializations Programming Guide.
翻译:
NSCoding协议声明了两个方法,一个类必须实现,因此这类的实例可以编码和解码。此功能提供了依据归档(对象和其他结构存储在磁盘上)和销售(对象被复制到不同地址空间)。
符合面向对象的设计原则,一个物体被编码或解码负责编码和解码实例变量。这样做的一个编码器指示对象通过调用encodeWithCoder:或initWithCoder:。encodeWithCoder:指示对象实例变量提供的编码器,编码一个对象可以接收这个方法任意次数。initWithCoder:指示对象初始化本身从编码器提供的数据;因此,它将取代任何其他初始化方法和每个对象只发送一次。任何对象类,应该codable必须采用NSCoding协议和实现它的方法。
考虑到可能的存档类型是很重要的,一个编码器支持。在OS X 10.2及以后版本,键控存档者优先。然而,你可能需要支持经典存档。,档案和序列化编程指南。
/**
* 从文件中解析一个对象的时候就会调用这个方法
* 通过xib或者storyboard创建UI控件就会调用这个方法
*/
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder:decoder]) {
// 代码
}
return self;
}
@protocol NSCoding
-(void) encoderWithCoder:(NSCoder *) aCoder;
-(id) initWithCoder:(NSCoder *) aDecoder;
@end
当对象需要保存自身时-encoderWithCoder:方法被调用
当对象需要加载自身时-initWithCoder:方法被调用
作用:通过xib或者storyboard创建UI控件就会调用这个方法
5、initWithFrame:
一般创建UI对象有两种方式。
一种是通过nib,一种是通过代码。
如果是通过代码创建,那么就会调用这个方法,进行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