根据苹果官网给的关系图做了一些验证
1.查看同一个类在内存中的个数
Class class1 = [HTPerson class];
Class class2 = [HTPerson alloc].class;
Class class3 = object_getClass([HTPerson alloc]);
Class class4 = [HTPerson alloc].class;
NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
输出了如下的结果。证明同一个类在内存中,只会创建一个地址。
0x100004990-
0x100004990-
0x100004990-
0x100004990
2.查询类的isa地址指向
通过系统方法获取类的内存地址,以及使用lldb
输出其内部结构
// NSObject实例对象
NSObject *object1 = [NSObject alloc];
// NSObject类
Class class = object_getClass(object1);
// NSObject元类
Class metaClass = object_getClass(class);
// NSObject根元类
Class rootMetaClass = object_getClass(metaClass);
// NSObject根根元类
Class rootRootMetaClass = object_getClass(rootMetaClass);
NSLog(@"\n%p 实例对象\n%p 类\n%p 元类\n%p 根元类\n%p 根根元类",object1,class,metaClass,rootMetaClass,rootRootMetaClass);
输出了如下结果:
得出结论:
- 实例对象的isa --> 类,
- 类的isa --> 元类,
- 元类对象isa --> 根元类
- 根元类isa --> 根元类
3.类的继承关系
根据图中的继承关系(类-父类-父父类-null
)做了如下验证:
Class nSuperClass = class_getSuperclass(NSObject.class);//NSObject元类的父类
NSLog(@"HTTeacher-类地址%p",HTTeacher.class);
NSLog(@"HTPerson-父类地址%p",HTPerson.class);
NSLog(@"NSObject-父父类地址%p",NSObject.class);
NSLog(@"NSObjectSuper-父父父类%@ -- 父父父类%p",nSuperClass,nSuperClass);
2021-06-20 18:34:30.592061+0800 002-isa分析[16955:397181] HTTeacher-类地址0x100008b40
2021-06-20 18:34:30.592425+0800 002-isa分析[16955:397181] HTPerson-父类地址0x100008af0
2021-06-20 18:34:30.592493+0800 002-isa分析[16955:397181] NSObject-父父类地址0x7fff94a3f118
2021-06-20 18:34:30.592555+0800 002-isa分析[16955:397181] NSObjectSuper-父父父类(null) -- 父父父类0x0
证明HTPerson 继承于 NSObject,NSObject继承于nil
4.类的内部结构
查看源码如下
在源码objc.h
中,可以看到 typedef struct objc_class *Class
。class属于objc_class的指针类型。
- 搜索 objc_class 可以找到如下三个成员:
struct objc_class : objc_object {
...
// Class ISA; //指向元类 8字节
Class superclass; //父类 8字节
cache_t cache; //缓存 结构体 16字节
class_data_bits_t bits; //对象方法和属性
...
}
- 查看
class_data_bits_t
struct class_data_bits_t {
...
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
...
}
- 查看
class_rw_t
里面有以下几个方法。
struct class_rw_t {
//方法列表
const method_array_t methods() const {...}
//属性列表
const property_array_t properties() const {...}
//代理方法
const protocol_array_t protocols() const {...}
}
5.根据内存地址中的存储内容进行验证:(使用到了内存地址平移
)
@interface LGPerson : NSObject{
NSString *subject;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;
- (void)sayNB;
+ (void)say666;
获取下面的输出结果:(x/4gx
打印类的内存。p/x
打印地址)
-
获取属性列表
获取bits地址时需要进行字节平移,平移了32位。
-
获取实例方法(类似获取属性列表
properties
改成-->methods()
)
-
获取类的成员列表
-
获取类方法列表(要去元类中去获取)
获取元类的地址
6.总结
类中有主要有isa
、superclass
、cache
、bits
成员变量,bits
中存储属性列表、实例方法列表、成员变量列表、协议列表等. 其中类的类方法存储在元类的bits
中。
搞完了,出去运动下。