对Category进一步了解


无论谁在设计一个类的时候多么nice,但是在以后的更新迭代中,都会感觉以前的类行为还是有点欠缺。那怎么办Objective-C 2.0 中提供了一个新的特性,就是可以动态的给一个类添加新的行为,这感觉这就是神一样的队友啊,虽然其他的语言也有这个特性。

category的作用

a)可以给一个类动态的添加新的行为。

b)可以将一个大的文件,分解为多个category文件,可以多个人共同开发同一个类。


Category和Extension的区别

一个和匿名的category相似的东西那就是Extension,但是她们的使用上有很大的区别

a)Extension 是在编译期决定的,在编译期间将和interface 、implement一起形成一个完整的类。

一个有源码的类可以添加Extension,所以无法给系统的类添加Extension。

b) Extension 可以添加实例变量。

c)Category 是在运行期决定的,不可以添加实例变量。



Category  内在有没有货

OC类和对象,在runtime层都是用struct表示的,category也逃脱不了

在runtime.h 中可以看到下面信息

typedef struct objc_category *Category;

struct objc_category {

    char *category_name                                      OBJC2_UNAVAILABLE;

    char *class_name                                         OBJC2_UNAVAILABLE;

    struct objc_method_list *instance_methods                OBJC2_UNAVAILABLE;

    struct objc_method_list *class_methods                   OBJC2_UNAVAILABLE;

    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;

}  

包含了

1)、类的名字(name)
3)、category中所有给类添加的实例方法的列表(instanceMethods)
4)、category中所有添加的类方法的列表(classMethods)
5)、category实现的所有协议的列表(protocols)
6)、category中添加的所有属性(instanceProperties)

从category的定义也可以看出category的可为(可以添加实例方法,类方法,甚至可以实现协议,添加属性)

不可以添加实例变量

下面可以写一个类添加两个category


然后调用下面这个方法即可将类中所有的方法,都可以列出来,可以验证Category中方法重写的问题。只是检测方法是顺序检测的,不知道后面还有一个同名的方法。

也可以在资源加载的时候将category的顺序换一下,即可得到不同的结果

- (void)testCategoryOverridSystemMethod

{

    typedef void (*functionn) (id, SEL);

    Class currentClass = [FirstObject class];

    FirstObject * myButton = [FirstObject new];

    if (currentClass) {

        unsigned int methodCount;

        //通过类名得到方法列表

        Method * methodList = class_copyMethodList(currentClass, &methodCount);

        //NSLog(@"method list :%@",methodList);

        IMP lastImp = NULL;

        SEL lastSel = NULL;

        for (NSInteger i = 0 ; i < methodCount; i ++) {

            Method method = methodList[i];

            //得到方法名并转为NSString

            NSString * methodName = [NSString stringWithCString:sel_getName(method_getName(method)) encoding:NSUTF8StringEncoding];

            NSLog(@"method Name :%@",methodName);

            if ([@"printName" isEqualToString:methodName]) {

                NSLog(@"into here   test Category   .... ");

                //得到方法对应的函数的指针

                lastImp = method_getImplementation(method);

                //得到方法的名字 SEL类型

                lastSel = method_getName(method);

                if (lastImp!= NULL) {

                    functionn f = (functionn)lastImp;

                    //传入类名/实例名 、方法的SEL、对应参数 开始调用方法

                    f(myButton,lastSel);

                }

            }

        }

        

        NSLog(@"out of for ....");

        if (lastImp!= NULL) {

            functionn f = (functionn)lastImp;

            //传入类名/实例名 、方法的SEL、对应参数 开始调用方法

            f(myButton,lastSel);

        }

        

      

        //释放方法列表

        free(methodList);

    }

    

    

    

}


现在基本可以知道为什么category中的方法的调用和构成了。

如果还想知道category中的方法是如何添加到类中可以使用命令

clang -rewrite-objc main.m

然后会编译出一个代码特别多的.cpp文件

可以自行阅读,这就不贴了,实在是太多了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值