TOP

【OC底层】OC对象本质,如 isa, super-class(一)
2019-08-31 01:05:11 】 浏览:69
Tags:底层 对象 本质 isa super-class

Objective-C的本质

1、我们编写的Objective-C,底层现实都是C/C++,代码生成步骤如下:

2、在OC中的所有面向对象的实现,都是基于C/C++的数据结构实现的

3、将Objective-C代码转换为C\C++代码

  xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件

    注:如果需要链接其他框架,使用-framework参数。比如-framework UIKit

 

一个OC对象在内存中是如何布局的? 

 

NSObject基类的实现:

 

子类的实现:

 

子类的拆解:

 1、在OC中的对象,就是 C++中的 struct来实现的

 2、每个OC对象中都会有一个 isa 的指针,isa指向的是 objc_class 结构体,如下(旧版OC原码):

通过代码可以看得出在OC2 中已经不能通过  objc_method_list 之类的方式获取方法名、实例、协议之类的了,需要使用新的方法获取

 

思路:自定义一个和oc源码中 objc_class 结构一样的结构体,然后将对象的isa 强转成我们自定义的那个,再去调用

如下是OC中objc_class的源码(新版OC原码):

新的OC版本中方法、属性、协议相关数据都存在了 bits 

通过 bits.data() 返回 class_rw_t 结构,如下:

bits.data() 的实现:

其中需要 通过 & FAST_DATA_MASK 才能获取到真实的地址

整体数据结构图:

 

 

 

 OC对象的分类

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

1、instance对象

  instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇iOS Push详述,了解一下? 下一篇snapkit equalto和multipliedby方..

kafka-
kafka   Partit
解决android studio
Kafka史上最详细原理
Error while fetchin
【Kafka】安装与快速
    &
flume读取日志数据写
Authentication plug
Flume 自定义source
flume   三大核
ICC副本>>>
愚公移山  
Hbase架构   Hb
5 hbase-shell + &
Hbase   MapRed
MetaException(messa
Exception in thread
HIVE metastore Dupl
-->