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

我們可以看到再一次調用了父類的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

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]);
    }
}
@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:
這個方法時遵守了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;
}

要編碼的對象,必須實現NSCoding協議。

@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
}

今天就先寫到這裏,後面會繼續完善…..

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章