深入理解Objective-C中类的数据结构
栏目: Objective-C · 发布时间: 5年前
内容简介:一、类的结构OC 中的代码在底层实现,使用的是 C、C++,所以要研究 OC 中的类结构,可以将 OC 的代码转成 C++的代码即可。首先看一下 NSObject 的结构是什么样子的,创建一个文件并简单的编写如下代码:进入终端,输入指令:
一、类的结构
OC 中的代码在底层实现,使用的是 C、C++,所以要研究 OC 中的类结构,可以将 OC 的代码转成 C++的代码即可。首先看一下 NSObject 的结构是什么样子的,创建一个文件并简单的编写如下代码:
// CustomFile.m #import <foundation foundation="" h=""> void test() { [NSObject alloc]; } </foundation>
进入终端,输入指令:
clang -rewrite-objc CustomFile.m
默认生成一个 CustomFile.cpp 文件。这个指令生成的代码会很多,也可以使用 xcrun 指令来指定一个特定的架构,这样的:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc CustomFile.m -o CustomFile_arm64.cpp
这样在 CustomFile_arm64.cpp 文件中会生成一个 真机下的运行代码。相比之下 CustomFile_arm64.cpp 文件会比 CustomFile.cpp 小了很多,但是对于查看 NSObject 的实际结构都是可以的。
打开任意一个 .cpp 文件,都可以找到这样的定义:
struct NSObject_IMPL { Class isa; };
其中 Class 的定义如下:
typedef struct objc_class *Class;
再来看一下在实际中的 NSObject 类的声明是什么样的:
@interface NSObject <nsobject> { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-interface-ivars" Class isa OBJC_ISA_AVAILABILITY; #pragma clang diagnostic pop } </nsobject>
简化后是这样的:
@interface NSObject { Class isa; }
总之Class 是一个指针,NSObject_IMPL是一个结构体,与 NSObject 在结构上极为相似。
二、类继承后的结构
创建一个 Person.m 文件,弄一个继承于 NSObject 的 Person 类。代码编写如下:
// Person.m #import <foundation foundation="" h=""> // 类的申明 @interface Person : NSObject @end // 类的实现 @implementation Person @end // 类的申明 @interface Student : Person @end // 类的实现 @implementation Student @end </foundation>
其中 Person 继承于 NSObject,Student 继承于 Person 于是在 .cpp 文件中找到这样的定义:
struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; }; struct Student_IMPL { struct Person_IMPL Person_IVARS; };
NSObject_IVARS 看着这个命名就可以猜到是将父类的所有 ivar 都继承过来了。
似乎明白了一个套路
在 NSObject 中只有一个 Class 类型的成员变量 isa,在没有自定义任何的成员属性的情况下,继承的子类中的 ivar 都来自于父类。
如果说给 Person 与 Student 都定义一个成员变量,是这样的:
struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; int _no; }; struct Student_IMPL { struct Person_IMPL Person_IVARS; int _age; };
终于对 Class 的一些套路有进一步的理解了。
三、添加方法后的结构
创建一个 FunClass.m 文件,编写代码如下:
// FunClass.m #import <foundation foundation="" h=""> // 类的申明 @interface FunClass : NSObject - (void)testInstance; + (void)testClass; @end // 类的实现 @implementation FunClass - (void)testInstance { } + (void)testClass { } @end </foundation>
最后发现在 .cpp 中类的结构没有任何的改变,是这样的:
struct FunClass_IMPL { struct NSObject_IMPL NSObject_IVARS; };
但是我们会发现另外一个问题,在 OC 中的方法变成这样的了:
// 实例方法 _OBJC_$_INSTANCE_METHODS_FunClass __attribute__ ((used, section ("__DATA,__objc_const"))) = { sizeof(_objc_method), 1, {{(struct objc_selector *)"testInstance", "v16@0:8", (void *)_I_FunClass_testInstance}} static void _I_FunClass_testInstance(FunClass * self, SEL _cmd) { } // 类方法 _OBJC_$_CLASS_METHODS_FunClass __attribute__ ((used, section ("__DATA,__objc_const"))) = { sizeof(_objc_method), 1, {{(struct objc_selector *)"testClass", "v16@0:8", (void *)_C_FunClass_testClass}} static void _C_FunClass_testClass(Class self, SEL _cmd) { }
发现这几个特点:
1、实例方法有这个:_INSTANCE_METHODS_FunClass,类方法的是这个:_CLASS_METHODS_FunClass
2、两个方法都是 static 方法
3、方法都多了两个参数:self 与_cmd,这也回答了为什么 self 与 _cmd 只能在方法中有的根本原因。
关于 方法 的这部分先介绍到这里,后期会有专门的专题。
作者:给策
链接:https://www.jianshu.com/p/04cc4f912603
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入理解 MySQL 索引底层数据结构
- 深入理解 MySQL 索引底层数据结构
- 深入 LevelDB 数据文件 SSTable 的结构
- 深入剖析Redis系列(六) - Redis数据结构之哈希
- 深入剖析Redis系列(七) - Redis数据结构之列表
- 深入剖析Redis系列(八) - Redis数据结构之集合
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Just My Type
Simon Garfield / Profile Books / 2010-10-21 / GBP 14.99
What's your type? Suddenly everyone's obsessed with fonts. Whether you're enraged by Ikea's Verdanagate, want to know what the Beach Boys have in common with easy Jet or why it's okay to like Comic Sa......一起来看看 《Just My Type》 这本书的介绍吧!