首先我们要明白什么是category
类扩展class extension
我们有一个ZKPerson类如下里面会有属性,以及instance方法和class方法
那什么是类扩展呢
类扩展和分类Catgory一样都是可以给类增加定义属性和方法。
我们新建ZKPerson两个分类(Test) (Eat)如下
我们再将ZKPerson+(Eat)转化成cpp文件
(xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc ZKPerson+Eatm),以便查看category的底层。
我们会发现category底层结构为一个_category_t的结构体
也就是说当我们每创建一个分类,系统在编译时候就会把这个分类转化成这样一个结构体并保存起来。
当我们在程序运行时runtime,所有分类的这些属性方法等将会合并到Person里面,分类的对象方法合并到Person类对象里面,分类的类方法合并到Person元类对象里面。runtime合并过程源码如下:
查看下attachLists是具体如何实现将分类方法加到类对象的方法列表中(原来的方法列表往后移,新的分类的方法列表放在原来的方法列表前面)
就此,我们可以看到后面合并进来的分类方法列表是放在数组的前面的,最后把所有分类的方法列表合并到原有类的方法列表前面。也就是说后编译的分类数据会在数组的前面,当我们调用时会优先调用数组前面的方法。
我们可以实践一下,编译前记得在Target-BuildPhase-Compile Sources中删除我们的cpp文件,不让它参与编译,我们调用[person run]实例方法,首先我们的编译顺序是这样的,先编译Test分类,然后时Eat分类,最后是Person类
因为Eat分类是最后编译的,所以调用的是Eat分类的run方法。虽然Person类是最后编译,但是从上述源码中看到所有分类的方法合并时是放在Person类方法列表前面的。不管Person类何时编译,只要它有分类就会把分类的方法列表合并到Person类的方法列表前面。所以我们调用时分类会覆盖Person类的方法。
总接:
1、什么时候用到category
给系统类添加方法、属性(需要关联对象)。
对某个类大量的方法,可以实现按照不同的名称归类。
2、category的实现原理
答:category编译之后的底层结构是struct category_t,里面存储着分类的对象方法,类方法,属性,协议信息,在程序运行的时候,runtime会将category的数据,合并到原有类信息中(类对象,元类对象中)
3、category的加载处理过程
答:
1)、通过Runtime加载某个类的所有category数据
2)、把所有category的方法,属性,协议数据,合并到一个大数组中,后面参与编译的category数据,会在数组的前面
3)、将合并后的分类数据(方法,属性,协议),插入到类原来数据的前面
4)、分类的调用顺序是后编译的先调用
3、category和类扩展class extension的区别?
答:category是在运行时将方法属性合并到类对象里面,而类扩展是在编译的时候就将方法属性等合并到类对象里面
内容转自于此篇华文 >
1、定义的一个类,里面有一个私有变量mt_,并且在初始化值为"HaHa Ha"。@interface Mobj : NSObject {@privateNSString mt_;}@end@implementationMobj- (id)init {self = [super init];if (self) {mt_ =[[NSString alloc] initWithString:@"Ha Ha Ha"];}return self;}- (void) dealloc {[mt_ release];记得加头文件#import<objc/runtimeh):NSStringstr;Mobj obj =[[Mobj alloc] init];object_getInstanceVariable(obj, "mt_", (void)&str);Ok,这样就实现了私有变量的访问。
浅拷贝:
1指针拷贝,没有开辟新的内存;
2生成一个新的指针变量指向原有对象的地址;
3原有对象引用计数+1。
深拷贝:
1从堆中开辟一份新的内存给新的对象,并将原有对象的信息赋值给新的对象;
2生成一个新的指针变量指向新的对象;
3原有对象引用计数不会增加,新的对象引用计数为1。
完全拷贝:
1是对多层对象包含或者集合中存储对象而言的;
2被拷贝对象的每一层都进行了深拷贝;
3例如集合中的对象,对象中的对象等。
示例:
打印输出:
结论:
示例:
打印输出:
结论:
示例:
打印输出:
结论:
示例:
打印输出:
结论:
在OC中不是所有的类都支持拷贝,只有遵循 NSCopying 才支持copy,只有遵循 NSMutableCopying 才支持mutableCopy。
NSObject有一个实列方法叫做 - (id)copy 。在OC源码中可以看到,默认的copy方法调用为:
对于采纳了 NSCopying 协议的子类,需要实现 copyWithZone 方法,否则会引发异常。 NSMutableCopying 只有在MRC模式下使用。
示例:
结论:
自定义类通过重写 copyWithZone 方法实现了深拷贝,通过 copy 方法(该方法默认调用 copyWithZone 方法)复制得到p1,从结果可以看出:深复制对象和和源对象的地址是不一样的。
NSCoping官方文档
自定义对象的copy和mutableCopy
类别 是一种为现有类添加新方法的方式,我们有时可以见到 “类名称+类别名称” 的命名方式。
类别可以添加属性 property ,但是不能添加实例变量。
下面我们来创建一个基于UILabel的类别,增加一个自适应Label的方法~
这里我特意添加前缀 kimi ,来避免方法名称冲突。
该方法作用是根据 content 内容实现 UILabel 的自动换行和调整字体发小,使Label能够合理显示内容。
运行可以看到效果, selflabel 实现了自适应字体大小和换行:
以上就是关于OC基础-category(1)全部的内容,包括:OC基础-category(1)、OC 类的结构分析、如何从oc中去获取一个私有的变量.....等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)