OC对象的本质

Objective-C

Objective-C是C语言的超集,我们平时写得OC,底层的实现都是C\C++代码,OC的对象、类是基于C\C++的结构体实现的。
可以使用以下命令行将OC代码转换为C\C++代码(只能作为参考不一定百分百准确)

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc <OC源文件> -o <输出的.cpp文件>

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

NSObject

一般我们写的对象都继承于NSObject,所以弄清楚NSObject相当关键

  • NSObject底层实现相关源码
struct NSObject_IMPL{
  Class *isa
}
//Class是objc_class结构体指针
typedef objc_class *Class

NSObject类里只有Class isa指针,所以obj对象的地址值就是isa指针的地址值。表面上看之只占用了8个字节(指针变量8个字节),阅读OC源码可以看到实质是分配了16个字节。
可以使用以下API查看内存使用情况

//一个实例对象至少需要多少字节
class_getInstanceSize([NSObject class]);
//一个实例对象实际占用多少字节
malloc_size((__brige const void *)obj);

一个继承NSObject的类的结构体

//例如
@interface Person : NSObject
@property (nonatomic, assign) int age;
@end
struct Person_IMPL{
  stuct NSObject_IMPL NSObject_IVARS;
  int _age;
}
//NSObject_IMPL的成员变量只有isa指针一个,所以实际结构体等价如下,person实例对象的地址值还是isa指针的地址值,再继承也同理
struct Person_IMPL{
  Class *isa;
  int _age;
}
OC对象分类

OC对象分为三类:instance对象(实例对象)、class对象(类对象)、meta-class对象(元类对象)

  • instance对象:通过类alloc出来的对象,每次alloc都会创建新的实例对象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
//obj1、obj2都是instance对象,它们是不同的两个对象,分别占据着不同的内存

instance对象在内存中存储的信息有isa指针和其他成员变量。

  • class对象(类对象)
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

objectClass1 ~ objectClass5都是NSObject的class对象
它们都是同一个对象,每一个类在内存中有且只有一个class对象
class对象在内存中存储的信息主要包括:
isa指针
superclass指针
类的属性信息(@property)、类的对象方法信息(instance method)
类的协议信息(protocol)、类的成员变量信息(ivar)

  • meta-class(元类对象)
//获取元类对象的方法
Class objMetaClass = object_getClass([NSObject class]);
/*
  注意:这个方法获取到的还是类对象
  Class objMetaClass = [[NSObject class] class];
*/

objectMetaClass是NSObject的meta-class对象(元类对象)
每个类在内存中有且只有一个meta-class对象
meta-class对象和class对象的内存结构是一样的,只是用途不一样而已,在内存中存储的信息主要包括:
isa指针
superClass指针
类的类方法信息
......

  • Class的结构
//struct objc_class 结构
struct objc_class{
  Class isa;
  Class superclass;
  Cache_t cache;//方法缓存
  class_data_bit_t bit;//用于获取类的具体信息
}
// bit & FAST_DATA_MASK 得到类的具体信息
struct class_rw_t {  // rw表示可读写
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
    method_array_t methods; //method_t 二维数组
    property_array_t properties; //属性二维数组
    protocol_array_t protocols; //协议二维数组
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
}
//struct class_ro_t 的结构
struct class_ro_t { //ro表示只读
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif
    const uint8_t * ivarLayout;
    const char * name; //类名
    method_list_t * baseMethodList; //方法列表
    protocol_list_t * baseProtocols; //协议列表
    const ivar_list_t * ivars; //成员变量列表
    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
}
isa指针和supclass指针
  • instance的isa指针指向class
    instance调用对象方法时,通过isa指针找到class,找出对应的对象方法进行调用
  • class的isa指针指向meta-class
    调用类方法时,通过class的isa找到meta-class,找出对应的类方法进行调用

从Arm64开始,优化了isa指针,isa & ISA_MASK才是真正的地址值

  • class对象的superclass指针指向父类class对象
    当instance调用父类对象方法时,先通过isa指针找到class,再通过class对象的superclass指针找到父类,然后再找出对应对象方法进行调用
  • meta-class对象的superclass指针指向父类的meta-class对象
    调用父类类方法时,通过class的isa找到meta-class,再通过meta-class对象的superclass指针找到父类,然后再找出对应的类方法进行调用


    isa、superclass总结
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,271评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,533评论 3 405
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,580评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,203评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,204评论 6 401
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,664评论 1 316
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,014评论 3 431
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,991评论 0 280
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,536评论 1 326
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,558评论 3 347
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,678评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,267评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,997评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,429评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,580评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,259评论 3 382
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,744评论 2 366

推荐阅读更多精彩内容