美文网首页
iOS中的Category

iOS中的Category

作者: 面朝对象_春暖花开 | 来源:发表于2019-06-12 17:26 被阅读0次

https://tech.meituan.com/2015/03/03/diveintocategory.html

总结下来有几点:

1、Category中添加的方法,和本类中添加方法一样(实例方法在objc_class的methodList中)、(类方法在metaClass的methodList中)

问:那为什么Category的同名方法会“覆盖”本类的同名方法?

>答:并不是覆盖,而是重新添加了一次,调用等于方法寻址,找到地址低的那个方法,就调用了,
高的那个方法等于没用。


#问:如果有两个Category同时实现了同名方法,谁会被调用呢?

>答:要看compile Source的添加顺序,后添加的那个被调用

#问:两个Category都加了+(void)load方法,怎么调用呢

>答: 先类后category,而category的+load执行顺序是根据编译顺序决定的,先添加的那个先调用

2、Category中关联的对象(objc_setAssociatedObject、objc_getAssociatedObject)是怎么存储的呢?

这个问题,其实是问objc_setAssociatedObject添加的objc在哪里存储

答:程序启动的时候,会初始化一个AssociationsManager,它管理了一个static的AssociationsHashMap,这里面存储着所有对象关联的对象,这个map的key就是对象的指针,value是另外一个AssociationsHashMap,当对象销毁时,销毁对应的KV对。

3、这是个自己想到的问题,为什么不在预处理阶段,把category和本类合并,这样能添加成员变量、成员属性、成员方法?

这个问题,实际是说,为什么category是在运行期间决议的呢?

答:感觉:节省空间,对象大小取决于变量的多少,有的对象不用category中的属性,没必要为它开空间。比如你为NSObject声明几个category,并且set了几个变量,那么你整个工程中所有的对象,都大了一圈,所有只能是运行期间决议。

4、为什么category不能声明成员变量?

答:既然知道category是运行时期间动态为对象赋予的,那么就很好理解了。
OC的对象其实是个struct,大小由其成员变量多少决定,寻找变量也是通过首地址加偏移量的方式寻找对应的变量,而每个对象地址及大小都在编译阶段由对象对应的class定死了。如果声明变量,等于class的内存空间要增加,这样这个运行期的内存布局全乱套了,用官方的解释就是,这是灾难性的。
所有,由于category是运行期决议的,才是导致它不能声明变量的原因。

5、验证一点:

C++中用一个struct(也就是class),new一个对象,这个对象的大小是由struct中变量所占空间决定的,也就是每一个new出来的对象大小,是所有变量所占空间的和(这个结论是理论上的,因为可以能虚表等等),关键是和方法没关系,方法存在代码区,new出来的对象存在栈里面。所以结论是:成员变量和成员方法,不一样,每个对象都有自己的成员变量,但是所有对象共享成员方法。
比如:

    ```
MyClass * obj1 = [MyClass new];
obj1->int_a = 1;

[obj1 logName1];

MyClass * obj2 = [MyClass new];
obj2->int_a = 2;

[obj2 logName1];
    ```

然后再logName1方法中打印调用栈:

- (void)logName1{
    
    NSLog(@"%@",[NSThread callStackSymbols]);
}

结果如下:发现调用logName1,都到到0x000000010f1b56cf这个地址

0   学习数据结构demo              0x000000010f1b56cf -[MyClass(abcd) logName1] + 47

相关文章

网友评论

      本文标题:iOS中的Category

      本文链接:https://www.haomeiwen.com/subject/qkxrfctx.html