先拋出 分類Category 的底層結(jié)構(gòu)
Category的用法經(jīng)常用到荒叼,第一印象就是給一個類擴展方法
本文主要分析一下三個問題
1.分類的方法的運行原理以及它方法的運行順序
2.從分類角度深入分析load initialize 方法的調(diào)用原理及調(diào)用順序
3.關(guān)聯(lián)屬性的實現(xiàn)原理
1.分類的方法的運行原理以及它方法的運行順序
在isa指針看繼承關(guān)系中我們知道一個實例對象的方法存放在它的class對象中叔营,那么我們給一個類添加的Cateogry方法是否也存放在它的類的class對象中
先看代碼
@interface Person : NSObject
- (void)run;
@end
@implementation Person
- (void)run
{
NSLog(@"Person - run");
}
@end
@interface Person (Test)
- (void)test;
@end
@implementation Person (Test)
- (void)test
{
NSLog(@"test");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
[person run];
[person test];
}
return 0;
}
[person run] 與 [person test] 都運行了柒竞,看編譯后的代碼如下:那么有上面的解釋可看出逢慌,一個類的分類方法會優(yōu)先類的方法調(diào)用工闺,因為它在class類的方法數(shù)據(jù)結(jié)構(gòu)的前面,所以會優(yōu)先調(diào)用匆篓,那么可以解釋如下代碼
@interface Person : NSObject
- (void)run;
@end
@implementation Person
- (void)run
{
NSLog(@"Person - run");
}
@end
@interface Person (Test)
- (void)test;
@end
@implementation Person (Test)
- (void)run
{
NSLog(@"Person(test) - run");
}
- (void)test
{
NSLog(@"test");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
[person run];//會調(diào)用分類中的run方法
}
return 0;
}
2.從分類角度深入分析load initialize 方法的調(diào)用原理及調(diào)用順序
只給出結(jié)論,不再展開分析
3.關(guān)聯(lián)屬性的實現(xiàn)原理
默認情況下寇窑,因為分類底層結(jié)構(gòu)的限制鸦概,不能添加成員變量到分類中,但是可以通過關(guān)聯(lián)對象來間接實現(xiàn)
關(guān)聯(lián)對象提供了以下API
//添加關(guān)聯(lián)對象
void objc_setAssociatedObject(id object, const void *key, id value,objc_AssociationPolicy policy)
//獲取關(guān)聯(lián)對象
id objc_getAssociatedObject(id object, const void *key)
//移除所有的關(guān)聯(lián)對象
void objc_removeAssociatedObjects(id object)
key的最優(yōu)用法
objc_setAssociatedObject(obj, @selector(getter), value, OHJC_ASS0CIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
實現(xiàn)原理(hashMap)
下篇筆記鏈接
iOS 底層解析-----Block (上)