从源码看本质
源代码:
@interface XKPerson ()
@property (copy, nonatomic) NSString *name;
@end
@implementation XKPerson
+ (instancetype)personWithName:(NSString *)name {
XKPerson *p = [XKPerson new];
p.name = name;
return p;
}
转化成cpp,整理相关代码:
// 对象信息的实际存储者
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
const unsigned char *ivarLayout;
const char *name;
const struct _method_list_t *baseMethods;
const struct _objc_protocol_list *baseProtocols;
const struct _ivar_list_t *ivars;
const unsigned char *weakIvarLayout;
const struct _prop_list_t *properties;
};
// 定义了XKPerson的元类
static struct _class_ro_t _OBJC_METACLASS_RO_$_XKPerson = {
1, sizeof(struct _class_t), sizeof(struct _class_t),
0,
"XKPerson",
(const struct _method_list_t *)&_OBJC_$_CLASS_METHODS_XKPerson,
0,
0,
0,
0,
};
// 定义了XKPerson的类对象
static struct _class_ro_t _OBJC_CLASS_RO_$_XKPerson = {
0, __OFFSETOFIVAR__(struct XKPerson, _name), sizeof(struct XKPerson_IMPL),
0,
"XKPerson",
(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_XKPerson,
0,
(const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_XKPerson,
0,
0,
};
// 对象的管理者
struct _class_t {
// 传说中的isa
struct _class_t *isa;
// 传说中的superclass
struct _class_t *superclass;
// 缓存相关
void *cache;
// 暂不使用
void *vtable;
// 对象信息的实际保存者
struct _class_ro_t *ro;
};
struct _class_t OBJC_METACLASS_$_NSObject;
// 是_class_t,用于管理_XKPerson元类
struct _class_t OBJC_METACLASS_$_XKPerson = {
0, // &OBJC_METACLASS_$_NSObject,
0, // &OBJC_METACLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_METACLASS_RO_$_XKPerson,
};
struct _class_t OBJC_CLASS_$_NSObject;
// 是_class_t,管理XKPerson的类对象
struct _class_t OBJC_CLASS_$_XKPerson __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_XKPerson,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_XKPerson,
};
// 真正使用的是_class_t,需要对齐进行初始化
static void OBJC_CLASS_SETUP_$_XKPerson(void ) {
// 所有元类的isa指向根源类,也就是metaNSObject
// metaNSObject的isa指向跟类对象,也就是classNSObject
OBJC_METACLASS_$_XKPerson.isa = &OBJC_METACLASS_$_NSObject;
// 元类的superclass指向父元类
OBJC_METACLASS_$_XKPerson.superclass = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_XKPerson.cache = &_objc_empty_cache;
// 类对象的isa指向元类
OBJC_CLASS_$_XKPerson.isa = &OBJC_METACLASS_$_XKPerson;
// 类对象的superclass指向父[类对象]
// 跟类对象(classNSObject)指向为nil,触发消息转发机制
OBJC_CLASS_$_XKPerson.superclass = &OBJC_CLASS_$_NSObject;
OBJC_CLASS_$_XKPerson.cache = &_objc_empty_cache;
}

为什么 [[obj class] class] 方法获取不到元类
实例对象、类对象、元类的获取代码如下:
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
NSObject *obj3 = [[NSObject alloc] init];
NSLog(@"instance address:%p %p %p",obj1, obj2, obj3);
NSLog(@"class address: %p %p %p",[obj1 class], [obj2 class], [obj3 class]);
NSLog(@"meta class address:%p %p %p",object_getClass([obj1 class]), object_getClass([obj2 class]), object_getClass([obj3 class]));
NSLog(@"error meta class address:%p %p %p",[[obj1 class] class], [[obj2 class] class], [[obj3 class] class]);
打印结果:
2020-11-04 09:05:26.264248+0800 XKObjTest[82779:33963605] instance address:0x10285f9a0 0x10285ffb0 0x10285e3d0
2020-11-04 09:05:26.265428+0800 XKObjTest[82779:33963605] class address: 0x7fff9b7d5140 0x7fff9b7d5140 0x7fff9b7d5140
2020-11-04 09:05:26.265520+0800 XKObjTest[82779:33963605] meta class address:0x7fff9b7d50f0 0x7fff9b7d50f0 0x7fff9b7d50f0
2020-11-04 09:05:26.265600+0800 XKObjTest[82779:33963605] error meta class address:0x7fff9b7d5140 0x7fff9b7d5140 0x7fff9b7d5140
Program ended with exit code: 0
我们都知道[[instance class] class]
这样是无法获取到元类的,那原因是什么呢?查找 objc 源码得到 class 方法的源码:
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
如上图所示,虽然 class 方法本质是调用 object_getClass,但是类方法 class 确是直接返回自己,也就是类对象,所以类对象无论调用多少次 class 方法,返回的都是类对象自己。
而 object_getClass 的源码如下:
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
这个方法直接返回的是 isa 指针的指向,所以可以获取到元类;
网友评论