根据苹果官网给的关系图做了一些验证
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地址指向
// 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 {...}
}
复制代码
根据内存地址中的存储内容进行验证:(使用到了内存地址平移
)
@interface LGPerson : NSObject{
NSString *subject;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;
- (void)sayNB;
+ (void)say666;
复制代码
获取下面的输出结果:(x/4gx打印类的内存。p/x打印地址)
输出方法列表类似操作即可:
总结
类中有主要有isa
、superclass
、cache
、bits
成员变量,bits
中存储属性列表、方法列表、成员变量列表、协议列表等.
搞完了,出去运动下。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END