Apple Documentation --Objective-C系列

方法名:initialize

聲明

+ (void)initialize;

討論

在這個類或集成與這個類的子類第一次被加載前,runtime 會發(fā)送initialize消息來調(diào)用這個方法。initialize消息是這個類從runtime中收到的第一個消息,父類接收到這個消息在子類之前。

runtime是以線程安全方式向類發(fā)送initialize消息,而且對這個類發(fā)送的第一個消息就是initialize消息,其他的線程如果嘗試發(fā)送消息給這個類將會阻塞知道initialize完成。

如果子類沒有實現(xiàn)initialize,父類的initialize也許會多次被調(diào)用。runtime會根據(jù)繼承關(guān)系來調(diào)用或者子類明確的指出調(diào)用[super initialize]。如果你想自己去管理或者控制這種多次調(diào)用,你可以在下方注釋的地方進行實現(xiàn):

+ (void)initialize {
  if (self == [ClassName self]) {
    // ... do the initialization ...
  }
}

因為initialize是以阻塞方式被調(diào)用的,所以在這個方法中應(yīng)盡可能減少代碼工作量,然后由于是阻塞方式調(diào)用所以任何調(diào)用其他類的代碼都可能導(dǎo)致死鎖。所以不要在initialize中進行復(fù)雜的邏輯,盡量簡化。

特別注意

initialize每個類只調(diào)用一次,如果你想對類和類的類別個字單獨進行初始化,你應(yīng)該實現(xiàn)load方法。

方法名:load

當(dāng)類或者類別被加入到runtime的時候進行調(diào)用,一般用于在類被加載前實現(xiàn)一些特殊的操作

聲明

+ (void)load;

討論

load消息在動態(tài)加載和靜態(tài)鏈接的時候都會被發(fā)送,但僅僅這個類或者類別實現(xiàn)這個方法的時候才會有相應(yīng)

初始化順序如下:

  1. 調(diào)用所有的Framework中的初始化方法
  2. 調(diào)用所有的+load方法
  3. 調(diào)用C++的靜態(tài)初始化方法及C/C++中的attribute(constructor)函數(shù)
  4. 調(diào)用所有鏈接到目標(biāo)文件的framework中的初始化方法

此外:

  • 一個類的+load方法在其父類的+load方法后調(diào)用
  • 一個Category的+load方法在被其擴展的類的自有+load方法后調(diào)用

+load方法中,可以安全地向其它無關(guān)的類發(fā)送消息,但接收消息的類中的+load方法可能尚未實現(xiàn)。

方法名:init

子類用來初始化一個新的對象,并立刻給該對象分配內(nèi)存

聲明

- (instancetype)init;

返回值

一個初始化的對象,如果因為某種原因沒有創(chuàng)建成果那么就會返回nil,這樣就不會拋出異常。

討論

一個init消息一定會與alloc(或者allocWithZone:)消息出現(xiàn)在同一行代碼中:

SomeClass *object = [[SomeClass alloc] init];

一個對象只有被初始化了才能被使用。

在一般情況下,你必須調(diào)用父類初始化方法來初始化并返回一個對象,如果不能初始化的話,就會返回nil。舉例,假設(shè)有一個類——BuiltInCamera類,這個類當(dāng)運行的設(shè)備中沒有攝像頭的時候進行初始化會返回nil

- (instancetype)init {
    if (self = [super init]) {
        // Initialize self
    }
    return self;
}

在一般情況下,你都要通過init來獲取返回對象,而不是通過alloc或者allocWithZone:


initialize,load,init 代碼示例

創(chuàng)建一個person類,并在其.m文件中實現(xiàn)以下三個方法

//
//  Person.m
//  AFNetworingSourceTest
//
//  Created by Mac on 2018/7/12.
//  Copyright ? 2018年 MJJ. All rights reserved.
//

#import "Person.h"

@implementation Person

+(void)initialize {
    NSLog(@"%s", __FUNCTION__);
}

-(instancetype)init {
    NSLog(@"%s", __FUNCTION__);
    return  self;
}

+(void)load {
    NSLog(@"%s", __FUNCTION__);
}
@end

然后在viewDidLoad中初始化兩個實例

- (void)viewDidLoad {
    [super viewDidLoad];
    Person* person1  = [[Person alloc]init];
    Person* person2  = [[Person alloc]init];
    // Do any additional setup after loading the view, typically from a nib.
}

控制臺打印:

2018-07-12 12:34:19.095313+0800 AFNetworingSourceTest[62407:43110238] +[Person load]
2018-07-12 12:15:31.053588+0800 AFNetworingSourceTest[61566:43077247] +[Person initialize]
2018-07-12 12:15:31.053690+0800 AFNetworingSourceTest[61566:43077247] -[Person init]
2018-07-12 12:15:31.053787+0800 AFNetworingSourceTest[61566:43077247] -[Person init]

可以看到盡管創(chuàng)建了2個實例,但是initialize只調(diào)用了一次,而且是在創(chuàng)建的時候被調(diào)用,然后init調(diào)用了兩次

接下來給Person創(chuàng)建一個子類Man

#import "Person.h"

@interface Man : Person

@end

#import "Man.h"

@implementation Man

@end

修改Personinitialize方法打印類名

+(void)initialize {
    NSLog(@"%s %@", __FUNCTION__,[self class]);
}

控制臺打印:

2018-07-12 12:31:47.690548+0800 AFNetworingSourceTest[62342:43103509] +[Person load]
2018-07-12 12:31:49.123319+0800 AFNetworingSourceTest[62342:43103509] +[Person initialize] Person
2018-07-12 12:31:49.123443+0800 AFNetworingSourceTest[62342:43103509] -[Person init]
2018-07-12 12:31:49.123572+0800 AFNetworingSourceTest[62342:43103509] -[Person init]
2018-07-12 12:31:49.123665+0800 AFNetworingSourceTest[62342:43103509] +[Person initialize] Man
2018-07-12 12:31:49.123740+0800 AFNetworingSourceTest[62342:43103509] -[Person init]

initialize方法輸出了兩次,一個子類沒有實現(xiàn)initialize方法,那么父類會調(diào)用這個方法兩次,一次為自己,另一次為子類。load方法在initialize之前調(diào)用


方法名:alloc

給對應(yīng)的類返回一個新的實例

聲明

+ (instancetype)alloc;

返回值

一個新的實例

討論

這個新的實例的isa指針被初始化為一個數(shù)據(jù)結(jié)構(gòu)體用來描述該類;其他實例變量的內(nèi)存被設(shè)置為0.

你必須使用init方法來完成初始化過程。
舉例:

TheClass *newObject = [[TheClass alloc] init];

初始化不要重寫alloc,而應(yīng)該根據(jù)每個類來實現(xiàn)其自身的init方法。

因為歷史原因,alloc會喚起allocWithZone:方法

方法名:allocWithZone

給對應(yīng)的類返回一個新的實例

聲明

+ (instancetype)allocWithZone:(struct _NSZone *)zone;

參數(shù)

zone 這個參數(shù)已被忽略,傳nil即可

返回值

一個新的實例

討論

這個新的實例的isa指針被初始化為一個數(shù)據(jù)結(jié)構(gòu)體用來描述該類;其他實例變量的內(nèi)存被設(shè)置為0.

你必須使用init方法來完成初始化過程。
舉例:

TheClass *newObject = [[TheClass allocWithZone:nil] init];

初始化不要重寫alloc,而應(yīng)該根據(jù)每個類來實現(xiàn)其自身的init方法。

這個方法沒用了,沒啥好看的

方法名:copy

返回一個從從copyWithZone:獲取的對象

聲明

- (id)copy;

返回值

返回的對象是從NSCopying協(xié)議的copyWithZone:方法中獲取

討論

使用NSCoping協(xié)議可以很方便的為一個類添加copy方法,當(dāng)然,一定要實現(xiàn)copyWithZone:方法,不然會拋出一個異常。
繼承于NSObject的類自身不提供NSCopying協(xié)議,子類必須對這個協(xié)議添加支持,并且實現(xiàn)copyWithZone:方法
子類的copyWithZone:調(diào)用順序:這個方法會首先向父類發(fā)送消息,并將其實現(xiàn),除非這個子類是直接從NSObject派生

方法名:copyWithZone

返回一個接收者(對象)

聲明

+ (id)copyWithZone:(struct _NSZone *)zone;

參數(shù)

zone
不用管這個參數(shù),直接可以忽略

返回值

一個對象

討論

當(dāng)你需要一個可以實現(xiàn)NSCopying協(xié)議的類時需要用到這個方法,要實現(xiàn)這個方法.例如,該方法允許您使用類對象作為NSDictionary對象的鍵,不用重寫這個方法

方法名:mutableCopy

mutableCopyWithZone 返回一個對象,zone參數(shù)為nil

聲明

- (id)mutableCopy;

返回值

返回的對象是由NSMutableCopying協(xié)議方法mutableCopyWithZone:返回,zone參數(shù)為nil

討論

對于采用NSMutableCopying協(xié)議的類來說,這是一種方便的方法。如果mutableCopyWithZone沒有實現(xiàn),則會引發(fā)異常。

方法名:mutableCopyWithZone:

返回一個對象

聲明

zone:用于創(chuàng)建內(nèi)存區(qū)域

討論

類對象可以使用這個方法來使自身符合NSMutableCopying協(xié)議,例如,該方法允許您使用類對象作為NSDictionary對象的鍵,不用重寫這個方法

方法名:dealloc

釋放對象占用的內(nèi)存

聲明

- (void)dealloc;

討論

如果在該對象內(nèi)存被釋放時候再次發(fā)送消息給該對象就會生成一個錯誤,可以重寫這個方法來釋放實例變量之外的對象的內(nèi)存釋放,例:

- (void)dealloc {
    free(myBigBlockOfMemory);
}

delloc的實現(xiàn)中,不要調(diào)用超類的實現(xiàn)。你應(yīng)該盡量避勉使用 dealloc 管理有限資源諸如文件描述符的生命周期。決不要直接發(fā)送 dealloc 消息。相反,任何對象的 dealloc 方法由運行時調(diào)用。參看 高級內(nèi)存管理編程指南 以獲得更詳細的內(nèi)容。

特別注意事項

當(dāng)未使用 ARC 時,你的 dealloc 實現(xiàn)必須把調(diào)用父類的實現(xiàn)作為最后一條指令。(隱含的意思就是,使用 ARC 時不能調(diào)用父類的實現(xiàn))

方法名:new

分配給接收類一個新實例,向它發(fā)送一個init消息,并返回初始化的對象。

聲明

+ (instancetype)new;

返回值

一個接收類的新的實例

討論

該方法是alloc和init的組合。與alloc一樣,它初始化新對象的isa實例變量,以便指向類數(shù)據(jù)結(jié)構(gòu)。然后調(diào)用init方法來完成初始化過程。

方法名:class

返回一個類對象

聲明

+ (Class)class;

返回值

一個類對象

討論

當(dāng)一個類是消息接受者是可以通過它的名稱來引用它。在其他所有情況下,類對象必須通過此方法或者類似方法獲得。例如,這里將SomeClass作為一個參數(shù)餐遞給isKindOfClass:方法(在NSObject協(xié)議中聲明):

BOOL test = [self isKindOfClass:[SomeClass class]];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容