技巧iOS基础知识记录与总结iOS Developer

OC面试基础(2)— 说说Category和Extension区

2017-04-05  本文已影响67人  Light413

Category 和 Extension介绍

Category

原类的方法还是存在的,并不是真的给覆盖了。因为在运行时当给对象发消息,会根据对象的‘isa’指针找到所属的类,然后在类的方法列表中根据方法名寻找,当找到第一个就返回了,而通过category添加的方法又在方法列表的最上面所以没有机会找到类原来方法`。

Extension

不同之处

eg:分别给自定义的User类添加Category,Extension

//Category
@interface User (InnterAdd)
-(void)test;
@end
@implementation User (InnterAdd)

-(void)test
{
    NSLog(@":%s",__func__);
}

@end

//Extension
@interface User ()

@property (copy)NSString * addr;

@end

表现形式上,Category有名称,有自己的.m文件,extension没有名称看起来像个匿名的分类,没有.m文件。 Category也可以没有名称,这样两者在表现上就一样了。

Category: 是在运行时加载处理的,这个过程中把添加的方法添加到类的方法列表中,由于类的内存结构布局是在编译时期确定的,所以在运行时不能再添加实例变量否则就破坏了内存结构(访问非法内存地址存在不可预知的错误,所以是禁止的)。那为啥能添加方法而不能添加成员变量呢?在runtime层,category用结构体category_t(在objc-runtime-new.h中可以找到此定义)如下:

typedef struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
} category_t;

从中可看出可以添加实例方法,类方法,甚至可以实现协议,添加属性。没有表示实例变量的存贮。

其实分类本身而言它就不是一个类,分类,分开类的一部分操作,就是一个在运行时给主类添加方法、属性、或者协议的操作或者对外提供的一种接口扩展,在分类中添加方法直接绑定到主类原有的方法列表。所以感觉把分类这个名字改为方法扩展更容易理解(o)/~,所以在这一点来看,Category和Extension在目的上还是一致的,都是对原有的类增加新的操作。

Extension:在编译时处理的,添加的变量和方法和类密切的在一起,就是类的一部分,类消失它也消失。

Category中关联对象

runtime提供了以下三个方法

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
objc_getAssociatedObject(id object, const void *key)
void objc_removeAssociatedObjects(id object)

其中objc_removeAssociatedObjects 移除已添加的所有对象,所以实际操作要注意别把其他地方添加的关联也给remove了。所以还是通过objc_setAssociatedObject 直接置为nil更为可靠。

#END

上一个问题:OC面试基础(1)— 说下@property关键字及修饰符

上一篇 下一篇

猜你喜欢

热点阅读