介绍
虽然Foundation不是开源的,但苹果其实是开源社区的主力军之一,这回我们主要研究Objective-C中的类与对象,其历史源码在这里, 写文章是版本是709版本, 旧版的重写文件还仍有保留
Class&Object定义
在Objc源码Public Headers中runtime.h
和objc.h
可以找到class和object的定义
/* OBJC_ISA_AVAILABILITY: `isa` will be deprecated or unavailable
* in the future */
#if !defined(OBJC_ISA_AVAILABILITY)
# if __OBJC2__
# define OBJC_ISA_AVAILABILITY __attribute__((deprecated))
# else
# define OBJC_ISA_AVAILABILITY /* still available */
# endif
#endif
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
struct objc_object {
objc_class *isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_class *Class; //类的定义
typedef struct objc_object *id; //对象的定义
苹果在Objective-C 2.0中试图模糊isa的内容,这样多了一层封装,并且isa也被OBJC_ISA_AVAILABILITY废弃,禁止直接访问了
接下来我们看看Project Headers中的相关定义,代码比较长,就只粘贴了部分在这里objc-runtime-new.h
和objc-private.h
typedef unsigned long uintptr_t;
typedef struct objc_class *Class;
typedef struct objc_object *id;
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
// ...
}
struct objc_object {
private:
isa_t isa;
public:
...
}
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
//...
}
struct protocol_t : objc_object {
...
}
Class object_getClass(id obj) {
if (obj) return obj->getIsa();
else return Nil;
}
其中struct objc_object中多了一个Union isa_t, isa_t中有两个构造函数其中bits和cls只能用其中一个
objc_class, protocol_t都继承了objc_object, 可以看出凡是带有isa结构的,就是objc中的对象. protocl也是对象,运行时可以通过isa指针,查找到该对象是属于什么类
Clang重写
苹果已经更新到866.9,转写代码大不相同,很多isa信息隐藏的更好,自定义类略有修改,当时Clang转写C++的代码
// 类定义
struct _class_t {
struct _class_t *isa;
struct _class_t *superclass;
void *cache;
void *vtable;
struct _class_ro_t *ro;
};
// 类定义的一部分
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
unsigned int reserved;
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;
};
// 实例
typedef struct objc_object PrisonCat;
// 父类
extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;
extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_CatAnimal __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_NSObject,
0, // &OBJC_METACLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_METACLASS_RO_$_CatAnimal,
};
extern "C" __declspec(dllimport) struct _class_t OBJC_CLASS_$_NSObject;
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_CatAnimal __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_CatAnimal,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_CatAnimal,
};
static void OBJC_CLASS_SETUP_$_CatAnimal(void ) {
OBJC_METACLASS_$_CatAnimal.isa = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_CatAnimal.superclass = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_CatAnimal.cache = &_objc_empty_cache;
OBJC_CLASS_$_CatAnimal.isa = &OBJC_METACLASS_$_CatAnimal;
OBJC_CLASS_$_CatAnimal.superclass = &OBJC_CLASS_$_NSObject;
OBJC_CLASS_$_CatAnimal.cache = &_objc_empty_cache;
}
// 子类
extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;
extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_PrisonCat __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_NSObject,
0, // &OBJC_METACLASS_$_CatAnimal,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_METACLASS_RO_$_PrisonCat,
};
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_CatAnimal;
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_PrisonCat __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_PrisonCat,
0, // &OBJC_CLASS_$_CatAnimal,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_PrisonCat,
};
static void OBJC_CLASS_SETUP_$_PrisonCat(void ) {
OBJC_METACLASS_$_PrisonCat.isa = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_PrisonCat.superclass = &OBJC_METACLASS_$_CatAnimal;
OBJC_METACLASS_$_PrisonCat.cache = &_objc_empty_cache;
OBJC_CLASS_$_PrisonCat.isa = &OBJC_METACLASS_$_PrisonCat;
OBJC_CLASS_$_PrisonCat.superclass = &OBJC_CLASS_$_CatAnimal;
OBJC_CLASS_$_PrisonCat.cache = &_objc_empty_cache;
}
#pragma section(".objc_inithooks$B", long, read, write)
__declspec(allocate(".objc_inithooks$B")) static void *OBJC_CLASS_SETUP[] = {
(void *)&OBJC_CLASS_SETUP_$_CatAnimal,
(void *)&OBJC_CLASS_SETUP_$_PrisonCat,
};
当objc_inithooks
启动回调时,程序会组装isa和superclass的关系, 可以看出isa关系:
Root判断源码
最后通过如下摘抄源码objc-runtime-new.h
可以画出一个类的关系图
bool isRootClass() {
return superclass == nil;
}
bool isRootMetaclass() {
return ISA() == (Class)this;
}
代码验证
通过运行时函数(object_getClass,class_isMetaClass,class_getSuperclass得到如下关系
测试代码运行如下:
isa: Kitty := PrisonCat := PrisonCat[meta] := NSObject[meta] := NSObject[meta] := ...
superclass: PrisonCat => CatAnimal => NSObject => nil
superclass: PrisonCat[meta] => CatAnimal[meta] => NSObject[meta] => NSObject => nil
首先,只看绿色的父类箭头,在OC中一切基类都是NSObject, NSObject没有父类
其次, isRootMetaclass使用了并查集的根节点判断, 也就是说meta class都属于同一个集合. 且NSObject[meta]为并查集的跟节点