OC Category 的几个点

Category 的结构引申

附加:Category 的处理过程

  1. Xcode在编译时,会将所有参与编译的分类转变成一个c++结构体(图1所示)


    图片 1.png
  2. 运行时通过runtime加载所有category数据,并将其方法、属性、协议数据按照编译顺序,分别合并到一个对应的大数组
    [后编译的在数组的前面] ----> 这样方法调用时就会优先调用后编译的分类方法
  3. 将合并后的分类数据(方法、属性、协议),插入到类(类对象、元类对象)原来数据的前面 ----> 优先调用分类方法

综上概括:

  1. 本质上所有对象方法、协议、属性最终都会按照分类在前,原类在后;后编译的分类在前,先编译在后的原则,分别存放在类对象对象方法、协议、属性对应的数组里面
  2. 所有类方法最终都会按照分类在前,原类在后;后编译的分类在前,先编译在后的原则,存放在元类对象类方法数组里面

结论

  1. 最终方法或属性等都一个数组,且有序,所以就有了方法调用顺序:后编译的分类方法-->先编译的分类方法-->类对象(元类对象)原来的方法
  2. 因为程序运行时runtime是把所有分类数据合并到原类所有数据中,所以不管有没有import 某个分类的头文件,这个分类中 重写的方法都会可能被调用
  3. 分类结构体中包含有属性数组``struct property_list *instanceProperties;,所以分类允许添加属性的,但需要手动实现getter 和setter(@proterty... 在分类声明属性,只会生成属性的getter 和setter声明,但不会实现,和生成带_的成员变量
  4. 分类结构体中不含有成员变量数组``struct property_list *instanceProperties;,可见分类不存在成员变量,也不能添加成员变量



拓展:如何给分类添加成员变量

  1. 上述结论中谈到:由于分类结构限制,分类不存在成员变量,也不能添加成员变量,但是我们可以用伪成员变量实现类似效果的
  1. 实现方案:
    a. 在分类interface用中@property声明一个属性
    b. 在分类implementation中实现属性的 getter 和setter。由于分类不能添加和生成成员变量,所以最常用且可靠的方案是通过Runtime API关联一个伪成员变量,来实现getter 和setter方法
  1. 关联对象的相关Runtime 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)

/** 参数说明:
 *  object :id类型, 一般都传 self;用途相当于一个字典的Key,
            用来归类所关联的成员变量; 
 *  key :const void * 类型指针,相当于读写属性值的Key,
         可以传用@selector(getter) --》 [这样能免除繁琐的宏或常量定义]
 *  value : 成员变量的值 (对象)
 *  objc_AssociationPolicy policy : 内存策略,相当于retain、strong、copy等
  1. 示例
#import <objc/runtime.h>

@interface TLPerson (ExampleCode)

@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int weight;
@end

@implementation TLPerson (ExampleCode)

- (void)setName:(NSString *)name
{
    /* policy 参数类型
    typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,          
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,                                            
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  
    OBJC_ASSOCIATION_RETAIN = 01401,      
    OBJC_ASSOCIATION_COPY = 01403      
    };*/
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name
{
    // 隐式参数
    // _cmd == @selector(name),
    // 用@selector(name)作为key,可以简化代码,省去一些宏定义,还有能有代码提示
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setWeight:(int)weight
{
    objc_setAssociatedObject(self, @selector(weight), @(weight), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (int)weight
{
    // _cmd == @selector(weight)
    return [objc_getAssociatedObject(self, _cmd) intValue];
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,278评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,076评论 1 32
  • 1. 使用 #import 相对c的 include 是防止头文件的重复导入 2. NSLog 相对于 print...
    迎风起飞的猪阅读 1,703评论 6 9
  • 你独自一人从楼梯的最边缘走下阶梯 我和我的朋友在欢声笑语中往上迈步 我似乎想起什么 猛然回头 却发现 你早已不在
    七年之灰阅读 150评论 0 1
  • 无意在QQ空间看到H发的一张被狗咬伤的病例,注意事项里的禁止辛辣让我想起了H在高考后答应请吃火锅的承诺。本着坑他...
    温慈Dorothy阅读 225评论 0 0