1. 类的结构是什么
在开发中,经常会自己去写一些类,但是类究竟是一个什么样的结构?
打开一份objc4-750源码,创建一个测试类 MyTest. 在main.h中实例化
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyTest *person = [MyTest alloc];
}
return 0;
}
在终端对main.h进行编译, 命令如下:
clang -rewrite-objc main.m -o main.cpp
得到一份遍以后的c++文件 main.cpp
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
MyTest *person = ((MyTest *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("MyTest"), sel_registerName("alloc"));
}
return 0;
}
这就是在main函数编译后的样子.但是重点并不是这里, 我们探索的是类的结构.所以就要找与class相关的东西.(因为万物都可以用Class来接收)
会发现这样的一个Class
typedef struct objc_class *Class;
在750源码的objc-runtime-new.h里找到objc_class:
从中得知, objc_class也是一个继承objc_object的结构体, 所以类也是一个对象.
其中还有一个隐藏的Class ISA; 那么这个ISA必然是继承自objc_object. 这也就是为什么一个对象内存中的第一个位置就是isa的原因 进入objc_object:
OC底层实际上就是对C的一层封装
2.类的属性与方法
2.1属性与成员变量
在之前的MyTest添加一个成员变量与属性
@interface MyTest : NSObject
{
NSString *testStr;
}
@property (nonatomic, strong) NSString *testStr2;
@end
运行后打印出这个类
0x001d800100001241: 代表isa
0x0000000100afe140: 代表superclass
接下来就是cache, 进入cache_t看一下结构:
那么可以得到: 0x00000001003a0e70 0x0000000000000000 :代表cache
通过上文看到objc_class有一个data()方法, 返回的是class_rw_t类型,看一下结构
根据之前的操作,对内存进行偏移,可以知道,一个类的首地址向右偏移32个字节就是bits的指针了. p一下bits指针
看一下$11的内容
这里面也可以看到属性. 通过修改属性名增加额外属性做验证
可以看到两个属性都可以找到, 但是却在class_rw_t中找不到相对应的成员变量. 那么肯定是存在另外一个地方, 根据命名来看,其他的都不是很符合. 唯有一个class_ro_t很可疑.进入结构体:
struct class_ro_t {
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;
method_list_t *baseMethods() const {
return baseMethodList;
}
};
继续上面的调试进入ro:
得到属性. 但是还说没有成员变量,它在哪里呢? 我们注意到class_ro_t中有一个ivars,打印出来
2.2类的方法
在上面我们同样看到有一个 baseMethods, 打印出来:
@interface MyTest : NSObject
{
NSString *testStr;
}
@property (nonatomic, strong) NSString *testStr2_rename;
@property (nonatomic, strong) NSString *testStr3;
- (void)add;
+ (void)class_add;
@end
重复步骤略.
由此可以得到一些结论:
- 类的属性、成员变量、实例方法、协议等都会存储在class_ro_t这结构体中
- class_rw_t中也会存放类的属性、实例方法以及协议。
- 类方法是存储在元类中的