二、在OC中的全部面向对象的实现,都是基于C/C++的数据结构实现的数据结构
三、将Objective-C代码转换为C\C++代码架构
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件框架
注:若是须要连接其余框架,使用-framework参数。好比-framework UIKitiphone
NSObject基类的实现:布局
子类的实现:spa
子类的拆解:3d
一、在OC中的对象,就是 C++中的 struct来实现的指针
二、每一个OC对象中都会有一个 isa 的指针,isa指向的是 objc_class 结构体,以下(旧版OC原码):code
经过代码能够看得出在OC2 中已经不能经过 objc_method_list 之类的方式获取方法名、实例、协议之类的了,须要使用新的方法获取视频
思路:自定义一个和oc源码中 objc_class 结构同样的结构体,而后将对象的isa 强转成咱们自定义的那个,再去调用
以下是OC中objc_class的源码(新版OC原码):
新的OC版本中方法、属性、协议相关数据都存在了 bits
经过 bits.data() 返回 class_rw_t 结构,以下:
bits.data() 的实现:
其中须要 经过 & FAST_DATA_MASK 才能获取到真实的地址
Objective-C对象主要分为如下3类:
1> instance对象(实例对象)
2> class对象(类对象)存储实例方法列表等信息
3> meta-class对象(元类对象)存储类方法列表等信息
经过下面的代码能够分别获取3种对象:
NSObject* obj = [[NSObject alloc]init]; const char* className = [@"NSObject" cStringUsingEncoding:NSUTF8StringEncoding]; // 实例对象 NSLog(@"instance: %p",obj); // 类对象 NSLog(@"NSObject class: %p", [NSObject class]); // 同上 NSLog(@"obj class: %p", [obj class]); // 若是传实例对象,获取到的仍是类对象 NSLog(@"get class: %p", object_getClass(obj)); // 经过类名获取类对象 NSLog(@"objcClass: %p", objc_getClass(className)); // 元类对象 // 必须要传入类对象才能获取元类对象 NSLog(@"meta-class: %p", object_getClass([obj class])); // 经过类名获取元类对象 NSLog(@"objcMetaClass: %p", objc_getMetaClass(className)); // 判断是不是metaClass NSLog(@"isMetaClass1:%i",class_isMetaClass([NSObject class])); // 0 NSLog(@"isMetaClass2:%i",class_isMetaClass([[NSObject class] class])); // 0 NSLog(@"isMetaClass3:%i",class_isMetaClass(object_getClass([NSObject class]))); // 1
输出:
2018-09-27 14:39:37.363 OC_isa_supclass[1350:102454] instance: 0x100202b50 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] NSObject class: 0x7fff760140f0 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] obj class: 0x7fff760140f0 2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] get class: 0x7fff760140f0 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcClass: 0x7fff760140f0 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] meta-class: 0x7fff76014118 2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcMetaClass: 0x7fff76014118
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass1:0
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass2:0
2018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass3:1
1> 须要注意的是 object_getClass 方法,当传入的是实例对象,就会返回类对象,若是传入的是类对象就会返回元类对象
2> 还有一点就是 [[NSObject class] class] 这样是获取不到元类对象的,这样获取到的仍是类对象
3> 另外里面还有两个 objc_ 开头的方法,分别是获取类对象和元类对象,但它是传入类名字符串就能够了,须要转换成 C语言的char
一、instance对象
它们是不一样的两个对象,分别占据着两块不一样的内存
instance对象在内存中保存的信息包括:
1> isa指针
2> 其它成员变量
二、class对象
NSObject类对象只有一个,全部实例对象的class属性获取到的都是同一个类对象
class对象在内存中存储的信息主要包括:
1> isa指针
2> superclass指针
3> 类的属性信息(@property)、类的对象方法信息(instance method)
4> 类的协议信息(protocol)、类的成员变量信息(ivar)
....
三、meta-class对象
每一个类在内存中有且只有一个meta-class对象
meta-class对象在内存中存储的信息主要包括:
1> isa指针
2> superclass指针
3> 类的类方法信息(class method)
...
注:class 对象和 meta-class 对象都是 Class 类型的,它们其实结构都是同样的,class对象中同样会包含 类方法,只不过那个类方法是 空的而已。
一样,meta-class对象中也有 类的属性、对象方法、协议、成员变量,不过那些对应的值也都是空
上面咱们经过源码能够看到每一个对象都有一个 isa 指针,isa指针做用是干吗的呢?
经过上图能够看出:
1> instance的isa指向class
当调用对象方法时,经过instance的isa找到class,最后找到对象方法的实现进行调用
2> class的isa指向meta-class
当调用类方法时,经过class的isa找到meta-class,最后找到类方法的实现进行调用
superclass是用于找父类的,好比子类调用某个方法,若是子类中没有,就会去父类找,底层就是经过superclass找到父类的,以下图:
当Student的instance对象要调用Person的对象方法时,会先经过isa找到Student的class,而后经过superclass找到Person的class,最后找到对象方法的实现进行调用
meta-class中的superclass基本和 class对象中的同样,不过有一点点区别,如图:
当Student的class要调用Person的类方法时,会先经过isa找到Student的meta-class,而后经过superclass找到Person的meta-class,最后找到类方法的实现进行调用
有什么区别呢?从这图可能看不出来,区别就是若是基类的meta-class中都找不到类方法,那么它就会去从基类对象里面去找对象方法,OC的底层实际上是不区分 对象方法与类方法的。
这张图可以清楚的描述 isa和superclass的做用和关系,下面是备注了一下,看得更加懂点。
instance调用对象方法的轨迹:
实例对象会先经过isa找到class对象,判断里面有没有要调用的方法,若是有就直接调用,没有就会经过class对象中的superclass找到父类,而后在父类中判断是否有该方法,若是尚未就接着往上找。
class调用类方法的轨迹:
isa找meta-class,方法不存在,就经过superclass找父类,最后基类mate-class也没有的话还会去基类对象找,这样就会致使调用类方法可能会去调用实例对象的方法
上面已经说到了instance对象的isa指针指向的是class对象,那就是说instance对象的isa指针内存地址是否是就是class对象的内存地址呢?
若是在之前的32位系统中确实如此,在64位系统中不是的,里面有一个点操做, ISA_MASK
其中arm64和x86架构的这个 ISA_MASK的偏移地址是不同的,以下图:
class、meta-class对象的本质结构都是struct objc_class,以下图:
-----------------------------
本文参考借鉴MJ的教程视频,很是感谢.