码迷,mamicode.com
首页 > 其他好文 > 详细

Objective-C 源码(三)Category的实现原理

时间:2015-11-12 16:18:31      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

    Category的使用场景主要有3个:

        给现有的类添加方法;

        将一个类的实现拆分成多个独立的源文件;

        声明私有的方法。

    实现原理

    我们知道,无论我们有没有主动引入 Category 的头文件,Category 中的方法都会被添加进主类中。我们可以通过 - performSelector: 等方式对 Category 中的相应方法进行调用,之所以需要在调用的地方引入 Category 的头文件,只是为了“照顾”编译器同学的感受。

    打开 objc-runtime-new.mm 文件,可以找到 _read_images ()方法

if (cat->instanceMethods ||  cat->protocols  
                ||  cat->instanceProperties) 
            {
                addUnattachedCategoryForClass(cat, cls, hi);
                if (cls->isRealized()) {
                    remethodizeClass(cls);
                    classExists = YES;
                }
                if (PrintConnecting) {
                    _objc_inform("CLASS: found category -%s(%s) %s", 
                                 cls->nameForLogging(), cat->name, 
                                 classExists ? "on existing class" : "");
                }
            }

            if (cat->classMethods  ||  cat->protocols  
                /* ||  cat->classProperties */) 
            {
                addUnattachedCategoryForClass(cat, cls->ISA(), hi);
                if (cls->ISA()->isRealized()) {
                    remethodizeClass(cls->ISA());
                }
                if (PrintConnecting) {
                    _objc_inform("CLASS: found category +%s(%s)", 
                                 cls->nameForLogging(), cat->name);
                }
            }

    可以看到这个函数对Category做了如下处理:  

        将 Category 和它的主类(或元类)注册到哈希表中;

        如果主类(或元类)已实现,那么重建它的方法列表。

    在这里分了两种情况进行处理:Category 中的实例方法和属性被整合到主类中;而类方法则被整合到元类中。另外,对协议的处理比较特殊,Category 中的协议被同时整合到了主类和元类中。

    最终都是通过调用

remethodizeClass(Class cls)

    这个函数的主要作用是将 Category 中的方法、属性和协议整合到类(主类或元类)中,更新类的数据字段 data() 中 method_lists(或 method_list)、properties 和 protocols 的值。进一步,我们通过 attachCategoryMethods 函数的源码可以找到真正处理 Category 方法的 attachMethodLists 函数。

    它的主要作用就是将集中的久类方法和Category中新添加的方法整合成一个心的方法列表,并赋值给 method_lists 或者 method_list 。说明了:主类中的方法和Category中的方法在runtime看来并没有区别,它们是被同等对待的,都保存在主类的方法列表中。 

    runtime 对 Category 中方法的处理过程并没有对 +load 方法进行什么特殊地处理。因此,严格意义上讲 Category 中的 +load 方法跟普通方法一样也会对主类中的 +load 方法造成覆盖,只不过 runtime 在自动调用主类和 Category 中的 +load 方法时是直接使用各自方法的指针进行调用的。所以才会使我们觉得主类和 Category 中的 +load 方法好像互不影响一样。因此,当我们手动给主类发送 +load 消息时,调用的一直会是分类中的 +load 方法。


Objective-C 源码(三)Category的实现原理

标签:

原文地址:http://my.oschina.net/caijunrong/blog/529417

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!