目标的分类
Object- C中一切目标能够分为3类,实例目标,类目标,元类目标。其间我们开发者常用的承继自NSObject都归于实例目标,实例目标经过isa指针指向的是类目标。类目标经过isa指向的是元类目标。类目标和元类目标拥有相同的结构,都是来自objc_class。
objc_class结构
在objc4源码中查找objc_class能够找到其结构
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
}
其间isa指针式其承继自objc_object的。本文主要解说类结构中的isa、superclass、bits,cache的内容单放一篇。
isa在之前的内容里边现已讲过,主要是指向类目标或者元类目标的。
superclass是体现出承继联系的。
cache是办法缓存。
bits是类的其他信息,例如成员变量,办法列表,协议,特点。
留意:元类目标结构也是如此,但元类目标里边没有成员变量,协议,特点这些内容。
isa指向图
相信做iOS开发都必须掌握的一个图。
这儿对isa指向做一个简略的总结
实例目标的
isa指针指向对应的类目标,类目标的isa指针指向对应的元类目标,元类目标的isa指向基类的元类目标(根元类)。
能够简略的用lldb调试来验证一下。
- (void)test {
//
NSObject *objc = [[NSObject alloc] init];
//isa指向的就是类目标
Class objcClass1 = [NSObject class];
Class objcMetaClass = object_getClass([NSObject class]);
}

objc的isa指针的值,然后用这个值与运算ISA_MASK,得到的值,正好是类目标的地址。

ISA_MASK与运算得到元类目标的地址。
能够持续这样再操作一轮,得到的还是元类目标的地址。这是由于该类是NSObject,NSObject元类目标的isa是指向自己的(图中右上交的循环箭头)。

0x00000001d64226c0的高9位和低3位都是0所以没有做与运算,结果其实是相同的。
留意ISA_MASK的使用需要留意环境,我这儿是M1的模拟器。
superClass指向
superClass的指向也在上面那个经典的图中。这儿要留意superclass是objc_class才有的,所以实例目标是没有的。类目标的superclass指向父类目标,元类目标的superclass指向父类的元类目标,根元类目标的superclass指针指向 根类目标。根类目标的superclass是nil。
留意:根元类目标的superclass指针指向 根类目标,这个是有一个面试题的。
请听题:
@interface NSObject (Interview)
+ (void)foo;
@end
@implementation NSObject (Interview)
//能经过这个调用的原因是,NSObject的基元类的supclass为NSobject的元类
- (void)foo {
NSLog(@"IMP: -[NSObject foo]");
}
@end
- (void)test {
[NSObject foo];
}
上面的代码能执行成功么?这题要结合objc_msgSend一起看,调查的点就是根元类目标的superclass指针指向根类目标。
bits
类的结构中还有一个bits,里边也存了很多信息,我们先看bits的数据结构 class_data_bits_t。
struct class_data_bits_t {
friend objc_class;
// Values are the FAST_ flags above.
uintptr_t bits;
public:
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
// Get the class's ro data, even in the presence of concurrent realization.
// fixme this isn't really safe without a compiler barrier at least
// and probably a memory barrier when realizeClass changes the data field
const class_ro_t *safe_ro() const {
class_rw_t *maybe_rw = data();
if (maybe_rw->flags & RW_REALIZED) {
// maybe_rw is rw
return maybe_rw->ro();
} else {
// maybe_rw is actually ro
return (class_ro_t *)maybe_rw;
}
}
}
其实最最重要的是其间的2个办法。data 和 safe_ro,两个办法分别返回class_rw_t 和class_ro_t。
这儿ro_t的获取也是经过data办法获取的,一切能够理解为ro_t也在rw_t之中。
class_rw_t
持续来看class_rw_t的数据结构。

rw_t中能够 看到有这3个办法,经过这三个办法分别能获取到类的办法、特点、协议。
class_ro_t
再看class_ro_t的数据结构。
能够看到有办法、特点、协议和成员变量。但办法、特点、协议的命名都是base注册的。



