在iOS中NSObject对象底层会转成 objc_class* 结构体指针类型, objc_class 结构体继承与 objc_object结构体, 内部有一个 isa_t isa 指针指向了结构体本身.
1. objc_object 结构
struct objc_object {
Class isa;
};
struct objc_class : objc_object {
Class isa; //继承与objc_object 如果是 实例对象指向当前类的 Class 实例, 如果是类对象 指向 metaClass
Class superclass; //父类 Class 指针
cache_t cache; // 缓存方法列表
class_data_bits_t bits; // 存储了类的有关信息
class_rw_t *data() const { // 类里边可读可写的信息 属于dirty memory, 还有一个 class_ro_t 只读信息 属于clean memory
return bits.data();
}
};
2. class_data_bits_t结构 可读可写类型 dirty memory
#define FAST_DATA_MASK 0x00007ffffffffff8UL
struct class_data_bits_t {
friend objc_class;
// Values are the FAST_ flags above.
// uintptr_t能够存储指针的无符号整数类型 通过 & FAST_DATA_MASK 拿到 class_rw_t信息
uintptr_t bits;
public:
// 类或者对象信息在这个 data 列表存储
class_rw_t* data() const {
class_rw_t *rw_t = (class_rw_t *)(bits & FAST_DATA_MASK);
return rw_t;
}
};
3. class_rw_t 和 class_ro_t结构 结构
struct class_rw_t {
const class_ro_t *ro; //存储只读类信息
method_array_t methods; // 方法列表
property_array_t properties; //属性列表
protocol_array_t protocols; //协议信息
char *demangledName; //类名
};
-
class_ro_t结构 只读类型 clean memory
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; //类名 MJPerson
method_list_t * baseMethodList; //方法列表
protocol_list_t * baseProtocols; // 协议信息
const ivar_list_t * ivars; // 成员列表
const uint8_t * weakIvarLayout;
property_list_t *baseProperties; //属性列表
};
class_rw_t提供了运行时对类扩展的能力,class_ro_t存储的是类在编译时就确定的一些信息。
将一些稳定不改动的数据放到class_ro_t 可以提高程序读取效率减少内存使用. 具体可参考 wwdc2020 developer.apple.com/videos/play…
4. 打印methods里边信息
由于网上大多数教程都是通过指针内存便宜 先拿到bits->data(), 再通过 bits->data()拿到 methods, 然后一点点获取内存 方法太过于繁琐 不如直接打印只管.
自己写了个get_methods()函数 打印所有方法信息, 如果是object类型打印出来实例方法(-), 如果是 class 类型打印出来类方法(+)
#封装了方法参数信息
@interface MJMethod_T : NSObject
@property (nonatomic, assign) IMP impl;
@property (nonatomic, assign) SEL selector;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *types;
@end
/// 获取所有方法列表
NSArray<MJMethod_T *> * get_methods() {
NSMutableArray *array = [NSMutableArray array];
auto const methods = this->methods();
for (const auto &meth2: methods) {
MJMethod_T *method = [[MJMethod_T alloc] init];
method.selector = meth2.big().name;
method.impl = meth2.big().imp;
method.types = [NSString stringWithCString:meth2.big().types encoding:NSUTF8StringEncoding];
method.name = NSStringFromSelector(meth2.big().name);
[array addObject:method];
}
return array;
}
控制台 log 打印方法信息
studentClassData -> (
"name = doSomething, types = v16@0:8, impl = 0x1091011a0",
"name = studentInstanceMethod, types = v16@0:8, impl = 0x109101180",
"name = height, types = i16@0:8, impl = 0x1091011c0",
"name = setHeight:, types = v20@0:8i16, impl = 0x1091011e0",
"name = test, types = v16@0:8, impl = 0x109101170"
)
5. 打印properties属性列表信息 property类型的属性都可以打印出来
/// 获取所有属性列表
NSArray <NSDictionary *> *get_properties() {
const property_array_t properties = this->properties();
if (properties.count() == 0) {
return @[];
}
NSMutableArray *array = [NSMutableArray array];
for (auto& prop : properties) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSString *name = [NSString stringWithUTF8String:prop.name];
NSString *attributes = [NSString stringWithUTF8String:prop.attributes];
dict[@"name"] = name ?: @"";
dict[@"attributes"] = attributes ?: @"";
[array addObject:dict];
}
return array;
}
控制台 log 打印 properties信息
6. 打印protocols信息
#打印所有协议信息
NSArray <NSDictionary *> * get_protocols() {
NSMutableArray *array = [NSMutableArray array];
const protocol_array_t protocols = this->protocols();
for (const auto& proto : protocols) {
NSMutableDictionary *hashMap = [NSMutableDictionary dictionary];
protocol_t p_t = *((protocol_t *)proto);
hashMap[@"isa"] = @{@"object": NSStringFromClass(p_t.isa)};
NSString *mangledName = [NSString stringWithUTF8String:p_t.mangledName];
hashMap[@"mangledName"] = mangledName;
method_list_t *instanceMethods = p_t.instanceMethods;
if (instanceMethods != NULL || instanceMethods != nullptr) {
hashMap[@"instanceMethods"] = __method_list_to_array(instanceMethods);
} else {
hashMap[@"instanceMethods"] = [NSNull null];
}
method_list_t *classMethods = p_t.classMethods;
if (classMethods != NULL || classMethods != nullptr) {
hashMap[@"classMethods"] = __method_list_to_array(classMethods);
} else {
hashMap[@"classMethods"] = [NSNull null];
}
method_list_t *optionalInstanceMethods = p_t.optionalInstanceMethods;
if (optionalInstanceMethods != NULL || optionalInstanceMethods != nullptr) {
hashMap[@"optionalInstanceMethods"] = __method_list_to_array(optionalInstanceMethods);
} else {
hashMap[@"optionalInstanceMethods"] = [NSNull null];
}
method_list_t *optionalClassMethods = p_t.optionalClassMethods;
if (optionalClassMethods != NULL || optionalClassMethods != nullptr) {
hashMap[@"optionalClassMethods"] = __method_list_to_array(optionalClassMethods);
} else {
hashMap[@"optionalClassMethods"] = [NSNull null];
}
hashMap[@"size"] = @(p_t.size);
hashMap[@"flags"] = @(p_t.flags);
struct protocol_list_t *protocols_list = p_t.protocols;
if (protocols_list != NULL || protocols_list != nullptr) {
NSMutableArray *list_arr = [NSMutableArray array];
for (const auto&meth_t: *protocols_list) {
[list_arr addObject:__protocol_list_t_to_array(meth_t)];
}
hashMap[@"protocols"] = list_arr;
} else {
hashMap[@"protocols"] = [NSNull null];
}
hashMap[@"_extendedMethodTypes"] = [NSString stringWithFormat:@"%p",p_t._extendedMethodTypes];
const char* _demangledName = p_t._demangledName;
if (_demangledName != NULL) {
hashMap[@"_extendedMethodTypes"] = [NSString stringWithUTF8String:_demangledName];
} else {
hashMap[@"_extendedMethodTypes"] = [NSNull null];
}
property_list_t *_classProperties = p_t._classProperties;
if (_classProperties != NULL) {
hashMap[@"_extendedMethodTypes"] = @[];
} else {
hashMap[@"_extendedMethodTypes"] = [NSNull null];
}
[array addObject:hashMap];
}
return array;
}
#打印协议中的方法信息
NSArray *__method_list_to_array(method_list_t *instanceMethods) {
NSMutableArray *array = [NSMutableArray array];
for (const auto&meth_t: *instanceMethods) {
NSMutableDictionary *hashmap = [[NSMutableDictionary alloc] init];
const struct method_t::big _b = meth_t.big();
hashmap[@"sel"] = NSStringFromSelector(_b.name);
hashmap[@"types"] = [NSString stringWithUTF8String:_b.types];
hashmap[@"imp"] = [NSString stringWithFormat:@"%p",_b.imp];
[array addObject:hashmap];
}
return [array copy];
}
#打印协议中继承的 protocol 比如 MJProtocol: NSObject协议
NSDictionary *__protocol_list_t_to_array(protocol_ref_t meth_t) {
NSMutableDictionary *hashMap = [NSMutableDictionary dictionary];
protocol_t p_t = *((protocol_t *)meth_t);
if (p_t.isa != nullptr) {
hashMap[@"isa"] = @{@"object": NSStringFromClass(p_t.isa)};
}
NSString *mangledName = [NSString stringWithUTF8String:p_t.mangledName];
hashMap[@"mangledName"] = mangledName;
method_list_t *instanceMethods = p_t.instanceMethods;
if (instanceMethods != NULL || instanceMethods != nullptr) {
hashMap[@"instanceMethods"] = __method_list_to_array(instanceMethods);
}
method_list_t *classMethods = p_t.classMethods;
if (classMethods != NULL || classMethods != nullptr) {
hashMap[@"classMethods"] = __method_list_to_array(classMethods);
}
method_list_t *optionalInstanceMethods = p_t.optionalInstanceMethods;
if (optionalInstanceMethods != NULL || optionalInstanceMethods != nullptr) {
hashMap[@"optionalInstanceMethods"] = __method_list_to_array(optionalInstanceMethods);
}
method_list_t *optionalClassMethods = p_t.optionalClassMethods;
if (optionalClassMethods != NULL || optionalClassMethods != nullptr) {
hashMap[@"optionalClassMethods"] = __method_list_to_array(optionalClassMethods);
}
hashMap[@"size"] = @(p_t.size);
hashMap[@"flags"] = @(p_t.flags);
return hashMap;
}
控制台输出protocols信息
(
{
"_extendedMethodTypes" = "<null>";
classMethods = "<null>";
flags = 0;
instanceMethods = "<null>";
isa = {
object = Protocol;
};
mangledName = MJProtocol;
optionalClassMethods = (
{
imp = 0x0;
sel = doSomething2;
types = "v16@0:8";
}
);
optionalInstanceMethods = (
{
imp = 0x0;
sel = doSomething;
types = "v16@0:8";
}
);
protocols = (
{
flags = 0;
instanceMethods = (
{
imp = 0x0;
sel = "isEqual:";
types = "B24@0:8@16";
},
..... 还有很多不再一一展示........
{
imp = 0x0;
sel = description;
types = "@16@0:8";
}
);
mangledName = NSObject;
optionalInstanceMethods = (
{
imp = 0x0;
sel = debugDescription;
types = "@16@0:8";
}
);
size = 96;
}
);
size = 96;
}
)
7. 打印class_ro_t结构体信息
class_ro_t 结构体成员信息
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
union {
const uint8_t * ivarLayout;
Class nonMetaclass;
};
explicit_atomic<const char *> name; //类名称
void *baseMethodList; // 方法列表 这里的方法都是类方法
protocol_list_t * baseProtocols; // 协议列表
const ivar_list_t * ivars; //成员列表
const uint8_t * weakIvarLayout;
property_list_t *baseProperties; // 属性列表
}
get_ro_t_info方法
/// 获取class_ro_t信息
NSDictionary * get_ro_t_info() {
const class_ro_t *ro_ptr = ro();
NSMutableDictionary *hashMap = [NSMutableDictionary dictionary];
[hashMap setObject:@(ro_ptr->flags) forKey:@"flags"];
[hashMap setObject:@(ro_ptr->instanceSize) forKey:@"instanceSize"];
[hashMap setObject:@(ro_ptr->instanceStart) forKey:@"instanceStart"];
[hashMap setObject:@(ro_ptr->reserved) forKey:@"reserved"];
[hashMap setObject:[NSString stringWithCString:ro_ptr->getName() encoding:NSUTF8StringEncoding] forKey:@"name"];
NSMutableArray *baseMethods = [NSMutableArray array];
for (const auto& meth2 : *ro_ptr->baseMethods()) {
MJMethod_T *method = [[MJMethod_T alloc] init];
method.selector = meth2.big().name;
method.impl = meth2.big().imp;
method.types = [NSString stringWithCString:meth2.big().types encoding:NSUTF8StringEncoding];
method.name = NSStringFromSelector(meth2.big().name);
[baseMethods addObject:method];
}
hashMap[@"baseMethods"] = baseMethods;
NSMutableArray *baseProperties = [NSMutableArray array];
for (auto& prop : *ro_ptr->baseProperties) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSString *name = [NSString stringWithUTF8String:prop.name];
NSString *attributes = [NSString stringWithUTF8String:prop.attributes];
dict[@"name"] = name ?: @"";
dict[@"attributes"] = attributes ?: @"";
[baseProperties addObject:dict];
}
hashMap[@"baseProperties"] = baseProperties;
hashMap[@"ivars"] = get_ivars();
protocol_list_t * baseProtocols = ro_ptr->baseProtocols;
if (baseProtocols != nullptr) {
NSMutableArray *list_arr = [NSMutableArray array];
for (const auto&meth_t: *baseProtocols) {
[list_arr addObject:__protocol_list_t_to_array(meth_t)];
}
hashMap[@"baseProtocols"] = list_arr;
} else {
hashMap[@"baseProtocols"] = @"nil";
}
return [hashMap copy];
}
log输出 class_ro_t信息
{
baseMethods = (
"name = doSomething, types = v16@0:8, impl = 0x108bd7430",
"name = studentInstanceMethod, types = v16@0:8, impl = 0x108bd7410",
"name = height, types = i16@0:8, impl = 0x108bd7450",
"name = setHeight:, types = v20@0:8i16, impl = 0x108bd7470",
"name = test, types = v16@0:8, impl = 0x108bd7400"
);
baseProperties = (
{
attributes = "Ti,N,V_height";
name = height;
},
{
attributes = "TQ,R";
name = hash;
},
{
attributes = "T#,R";
name = superclass;
},
{
attributes = "T@\"NSString\",R,C";
name = description;
},
{
attributes = "T@\"NSString\",R,C";
name = debugDescription;
}
);
baseProtocols = (
{
flags = 0;
isa = {
object = Protocol;
};
mangledName = MJProtocol;
optionalClassMethods = (
{
imp = 0x0;
sel = doSomething2;
types = "v16@0:8";
}
);
optionalInstanceMethods = (
{
imp = 0x0;
sel = doSomething;
types = "v16@0:8";
}
);
size = 96;
}
);
flags = 128;
instanceSize = 24;
instanceStart = 16;
ivars = (
{
alignment = 2;
name = "_weight";
offset = 16;
size = 4;
type = i;
},
{
alignment = 2;
name = "_height";
offset = 20;
size = 4;
type = i;
}
);
name = MJStudent;
reserved = 0;
}