先抛出 分类Category 的底层结构
分类数据结构.png
Category的用法经常用到,第一印象就是给一个类扩展方法
本文主要分析一下三个问题
1.分类的方法的运行原理以及它方法的运行顺序
2.从分类角度深入分析load initialize 方法的调用原理及调用顺序
3.关联属性的实现原理
1.分类的方法的运行原理以及它方法的运行顺序
在isa指针看继承关系中我们知道一个实例对象的方法存放在它的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] 都运行了,看编译后的代码如下:
编译后数据结构.png
它的数据结构就是如开始的数据结构表,这个数据表在运行时的时候会动态的添加到Person实例类的Class类中,动态添加过程如下:
category的加载处理过程.png
那么有上面的解释可看出,一个类的分类方法会优先类的方法调用,因为它在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)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];//会调用分类中的run方法
}
return 0;
}
2.从分类角度深入分析load initialize 方法的调用原理及调用顺序
只给出结论,不再展开分析
3.关联属性的实现原理
默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中,但是可以通过关联对象来间接实现
关联对象提供了以下API
//添加关联对象
void objc_setAssociatedObject(id object, const void *key, id value,objc_AssociationPolicy policy)
//获取关联对象
id objc_getAssociatedObject(id object, const void *key)
//移除所有的关联对象
void objc_removeAssociatedObjects(id object)
key的最优用法
objc_setAssociatedObject(obj, @selector(getter), value, OHJC_ASS0CIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
修饰符.png
实现原理(hashMap)
核心对象.png 实现过程 过程.png
下篇笔记链接
iOS 底层解析-----Block (上)
网友评论