联合体与位域
共用同一内存空间,联合体内占用空间最大的那个
@interface Trnk : NSObject
@property (nonatomic, assign) BOOL front;
@property (nonatomic, assign) BOOL back;
@property (nonatomic, assign) BOOL left;
@property (nonatomic, assign) BOOL right;
@end
#define DirectionFrontMask (1 << 0)
#define DirectionBackMask (1 << 1)
#define DirectionLeftMask (1 << 2)
#define DirectionRightMask (1 << 3)
@interface Tank () {
// 联合体
union{
char bits;
// 位域
strcut {
char front : 1;
char back : 1;
char left : 1;
char right : 1;
};
} _direction;
}
@end
@implementation LGTank
- (instancetype)init
{
self = [super init];
if (self) {
_direction.bits = 0b0000000000;
}
return self;
}
- (void)setFront:(BOOL)isFront {
if (isFront) {
_direction.bits |= DirectionFrontMask;
} else {
_direction.bits &= ~DirectionFrontMask;
}
}
isa 结构
isa 就是一个联合体(union isa_t )<长度8字节/64位>
nonpointer :标识是否对isa 指针开启指针优化 0:纯isa指针,1:不止是类对象地址,isa 中包含了类信息、对象的引用计数等has_assoc :关联对象标志位,0没有,1存在has_cxx_dtor :该对象是否有C++ 或者Objc 的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象shiftcls :存储类指针的值。开启指针优化的情况下,在arm64 架构中有33 位用来存储类。 newisa.shiftcls = (uintptr_t)cls >> 3 magic :用于调试器判断当前对象是真的对象还是没有初始化的空间weakly_referenced :标志对象是否被指向或者曾经指向一个ARC 的弱变量,没有弱对象的对象可以更快释放。deallocating :标志对象是否正在释放内存has_sidetable_rc :当对象引用计数大于10时,则需要借用该变量存储进位extra_rc :当表示该对象的引用计数值,实际上是引用计数值减1,例如,如果对象的引用计数为10,那么extra_rc 为9。如果引用计数大于10,则需要使用到has_sidetable_rc 来进行借位存储
union isa_t {
isa_t() {}
isa_t(uintptr_t value) : bits(value) {}
Class cls;
uintptr_t bits;
#if define(ISA_BITFIELD)
struct {
ISA_BITFIELD;
}
#endif
}
// arm64架构下 ISA_BITFIELD
uintptr_t nonpointer :1;
uintptr_t has_assoc :1;
uintptr_t has_cxx_dtor :1;
uintptr_t shiftcls :33;
uintptr_t magic :6;
uintptr_t weakly_referenced :1;
uintptr_t deallocating :1;
uintptr_t has_sidetable_rc :1;
uintptr_t extra_rc :19;
对象<isa >与类<cls >关联
- 对象的第一个属性必然是
isa ,由于其来自于父类 - 对象与类关联方式<
isa.bits & ISA_MASK = Class >
// 以下对象<obj>均为非TaggedPointer对象,且存在
// 根据对象获取类
Class object_getClass (id obj) {
if (obj) return obj->getIsa();
else return Nil;
}
objc_object::getIsa() {
if (!isTaggedPointer()) return ISA();
uintptr_t ptr = (uintptr_t)this;
if (isTaggedPointer()) {
// 省略...
} else {
// 省略...
}
}
objc_object::ISA() {
assert(!isTaggedPointer());
#if SUPPORT_INDEXED_ISA
if (isa.nonpointer) {
uintptr_t slot = isa.indexcls;
return classForIndex((unsigned)slot);
}
return (Class)isa.bits;
#else
return (Class)(isa.bits & ISA_MASK)
#endif
}
- 对象当前内存中可以有多个,类在当前内存中只存在一份
// class1~4结果一致,则可以证明类只存在一份
Class class1 = [Person class];
Class class2 = [Person alloc].class;
Class class3 = [Person alloc].class;
Class class4 = object_getClass([Person alloc]);
NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4)
类
类<Class >、元类<Meta Class >、根类<Root Class >、根元类<Root Meta Class >
-
类的内存第一个位置指向元类 -
类的内存是由系统创建,可以说类是通过元类进行创建的类对象 -
元类是由系统编译生成的 -
类对象的<isa >通过object_getClass(obj) 的方式获取到元类 -
元类的<isa >可以通过object_getClass(obj) 的方式获取到根类 -
根类的<isa >可以通过object_getClass(obj) 的方式获取到根元类 -
根元类的<isa >可以通过object_getClass(obj) 的方式获取到根元类 -
总结:对象isa -> 类、类isa -> 元类、元类isa ->根类、根类isa ->根元类 、根元isa -> 根元类
isa 流程图
- 虚线为
isa 流程图 - 实线为类继承关系
NSObject 的父类为nil ,根元类的父类是NSObject
|