Category:分类。
1、Category的使用场合是什么?
答:当需要将一个类拆分的时候使用。
2、Category的实现原理?
答:Category编译之后的底层结构是结构体struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息。
程序运行的时候,Runtime 会将Category的信息合并到类信息中(class类对象、mate-class元类对象),后合并的分类数据会插入到原来数据的前面;
分类没有自己的class对象、和mate-class对象,因为一个类只有一个class对象、mate-class对象。
3、Category和Class Extension的区别是什么?
答:Class Extension是在编译的时候,它的数据都已经包含在类信息中了;
Category是在运行的时候,才将数据合并到类信息中。
4、Category中有+load方法吗?+load方法什么时候调用?+load方法能继承吗?
答:有+load方法。
+load方法会在Runtime加载类、分类的时候调用;
每个类的+load方法只会调用一次;
先调用类的+load方法,(按照编译顺序,先编译,先调用),调用子类的+load方法之前,会先调用父类的+load方法;
再调用分类的+load方法,(按照编译顺序,先编译,先调用)。
这里+load方法调用的顺序比较特别,没有先调用分类的+load方法,因为+load方法的调用机制不是o bjec_msgSend的方式,+load是直接找到方法地址进行调用的。
load方法能继承,不过一般不会手动调用load方法,都是系统自动调用。
5、+intialize方法什么时候调用?
答:+intialize方法会在类第一次接收到消息的时候调用(eg:alloc方法);
先调用父类+intialize,再调能用子类的+intialize,先初始化父类,再初始化子类,每个类只会初始化1次(除父类),但是如果子类没有实现+intialize,会调用父类的+intialize,所以父类的+intialize可能会被调用多次;
+intialize是通过objc_msgSend进行调用的,是通过class类对象的isa找到mate-class元类对象里的+intialize方法进行调用,所以分类的+intialize方法会覆盖本身的+intialize。
6、Category能否添加成员变量,如果可以,如何给Cagegory添加成员变量?
答:默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中,但可以通过关联对象的方法来间接实现。
给分类添加属性时,分类会自动声明setter、getter方法,但是不会添加成员变量、也不会实现setter、getter方法。
可以通过Runtime API提供的C语言方法:
//添加关联对象
- (void)setAge:(NSInteger)age
{
objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_ASSIGN);
}
//获得关联对象
- (NSInteger)age{
return [objc_getAssociatedObject(self, _cmd) integerValue];
}
//@selector(age) 指的是age方法的内存地址
//_cmd 是当前方法的内存地址