其實有時間還是需要多補充下基礎知識的蔗坯,畢竟步子跨太大會扯到襠。
- load
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
這是 Apple Doc 上對 - load 的描述前鹅。(強行秀一波翻譯罐柳,其實我是個英語渣,最好還是看英文吧)當一個類或分類被添加到運行時的時候會觸發(fā)這個方法澈魄;實現(xiàn)這個方法可以在加載這個類時執(zhí)行一些特定的操作采章。
寫下 demo 看看這個方法在繼承樹上是什么執(zhí)行順序运嗜,雖然文檔里有寫。
- A class’s +load method is called after all of its superclasses’ +load methods.
- A category +load method is called after the class’s own +load method.
先執(zhí)行所有的父類的 - load 方法悯舟,分類的 - load 方法將會是最后執(zhí)行担租。
// Parent.m
+ (void)load {
NSLog(@"Parent load");
}
// Child.m
+ (void)load {
NSLog(@"Child load");
}
// Child+Category.m
+ (void)load {
NSLog(@"Child Category load");
}
有興趣的朋友可以自己去試試。
- initialize
Initializes the class before it receives its first message.
在收到第一條消息之前初始化類抵怎,也就是說你 #import 了這個類奋救,但是沒有用到這個類,就不會初始化它(有點懶加載的味道)反惕。
The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses. The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementation—or if subclasses explicitly call [super initialize].
runtime 會線程安全地發(fā)送 initialize 消息給類尝艘。父類會比它的子類先收到這個消息。如果子類沒有實現(xiàn) initialize 這個方法姿染,那么父類的 initialize 方法會被執(zhí)行多次 —— 否則 runtime 將會調(diào)用子類實現(xiàn) —— 除非子類明確調(diào)用 [super initialize] 背亥。
demo time。動手 ba 一 ba 。
// Parent.m
+ (void)initialize {
NSLog(@"Parent initialize");
}
// Child.m
+ (void)initialize {
NSLog(@"Child initialize");
}
// Child+Category.m
+ (void)initialize {
NSLog(@"Child Category initialize");
}
// main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
[Child new];
[Child new];
}
return 0;
}
結(jié)果中可以看出分類中的 initialize 會覆蓋掉類中 initialize 方法狡汉,而父類的 initialize 方法仍舊會被執(zhí)行娄徊。
接下來我們把子類中的 initialize 方法注釋掉,重新跑一遍看看結(jié)果盾戴。
發(fā)現(xiàn)父類的 initialize 方法被調(diào)用了兩遍寄锐,然后我們看文檔中的這段話。
The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program.
這段話的大致意思就是說 runtime 會發(fā)送 initialize 給這個類以及這個類的所有父類尖啡,因此當我們使用 Child 的時候橄仆,runtime 會先發(fā)送 initialize 消息給 Parent ,然后發(fā)送給 Child 可婶,但是 Child 沒有實現(xiàn) initialize 方法沿癞,所以就再次執(zhí)行了 Parent 的 initialize 。
所以如果使用一個 Grandson (沒有實現(xiàn) initialize)矛渴,則 Parent 的 initialize 將會被調(diào)用三次。
有時候我們可能需要這樣的效果惫搏,但是大多數(shù)時間我們是不需要這樣的具温,因此我們可以在實現(xiàn) initialize 時,這樣寫來避免這個問題筐赔。
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
用處(歡迎補充)
- load
在 load 中實現(xiàn)Method Swizzling:
+ (void)load {
Method a = class_getInstanceMethod([self class], @selector(logA));
Method b = class_getInstanceMethod([self class], @selector(logB));
method_exchangeImplementations(a, b);
}
- (void)logA {
NSLog(@"A");
}
- (void)logB {
NSLog(@"B");
}
- initialize
初始化一些靜態(tài)對象
// static NSArray *array = @[@1, @2]; //這樣是不行滴铣猩,編譯器不接受,只有數(shù)據(jù)類型才能這樣哦
static NSArray *array;
+ (void)initialize {
if (self == [Parent class]) {
array = @[@1, @2];
}
}
小結(jié)
| | load | initialize |
| :--- : | :-----: | :----: |
| 調(diào)用時機 | 類被添加到 runtime 時 | 類第一次接收到消息之前 |
| 調(diào)用順序 | 父類->子類->分類 | 父類 -> 子類(分類) |
| 調(diào)用次數(shù) | 1次 | 多次 |
| 顯式調(diào)用父類 | 否 | 否 |
| 分類中的實現(xiàn) | 類和分類都執(zhí)行 | 覆蓋類的實現(xiàn)茴丰,執(zhí)行分類的實現(xiàn) |
| 線程安全 | 安全 | 安全 |
上表主要就是這兩個方法的特點达皿,因為是線程安全的,所以在這兩個方法盡量少執(zhí)行復雜的操作贿肩,防止阻塞線程峦椰。
以上就是我對這兩個方法的描述,如有不對望指正汰规,給個喜歡以示支持汤功。