联合体与位域
共用同一内存空间,联合体内占用空间最大的那个
@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