目录
类的结构
- 类
Class
是一个objc_class *
类型的结构体指针 ,typedef struct objc_class *Class
- 结构体
objc_class
继承自结构体objc_object
strcut 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
class_rw_t *data() {
return bits.data()
}
// 省略...
}
objc_object
内包含一个isa
,因此每一个类里面都包含一个isa
,可以说万物皆对象
strcut objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
}
- 结构体
cache_t
部分代码
struct cache_t {
struct buckrt_t *_buckets;
mask_t _mask;
mask_t _occupied;
// 省略...
}
属性、实例方法、协议以及类方法存储
属性列表、实例方法列表、协议列表均在bits
内存储
- 获取属性列表存储位置的方式:<实例方法/协议类似>
- 第一步:根据类的首地址以及偏移量计算拿到
bits
的地址 - 第二步:通过
bits.data()
拿到class_rw_t *
的指针a
- 第三步:通过指针
a
可以拿到class_ro_t *
类型的指针ro
- 第四步:通过
ro.baseProperties
可以拿到一个property_list_t *
类型的指针b
- 第五步:打印指针
b
,可以看到属性(property
)列表
- 第一步:根据类的首地址以及偏移量计算拿到
- 另外通过
ro.ivars
可以拿到一个ivar_list_t *
类型的指针c
,打印指针c
,我们可以看到变量列表 - 通过打印指针
b
与指针c
对比可以发现,属性会在变量列表中编译出一个带有_
的变量 - 类方法存储在元类里面,可以先获取到类对象,然后根据
isa
读取到元类,再根据上述方式,进行查找元类里面的方法列表,就可以获取到类方法列表
相关结构体代码实现
class_rw_t
代码实现
struct class_rw_t {
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
Class firstSubClass;
Class nextSiblingClass;
char *demangledName;
#if SUPPORT_INDEXED_ISA
uint32_t index;
#elseif
void setFlags(uint32_t set)
{
OSAtomicOr32Barrier(set, &flags);
}
void clearFlags(uint32_t clear)
{
OSAtomicXor32Barrier(clear, &flags);
}
// set and clear must not overlap
void changeFlags(uint32_t set, uint32_t clear)
{
assert((set & clear) == 0);
uint32_t oldf, newf;
do {
oldf = flags;
newf = (oldf | set) & ~clear;
} while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&flags));
}
};
class_ro_t
代码实现
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
const char * name;
method_list_t * baseMethodList; //实例方法列表
protocol_list_t * baseProtocols;
const ivar_list_t * ivars; // 成员列表
const uint8_t * weakIvarLayout;
property_list_t *baseProperties; // 属性列表
method_list_t *baseMethods() const {
return baseMethodList;
}
};
method_array_t
代码实现
class method_array_t :
public list_array_tt<method_t, method_list_t>
{
typedef list_array_tt<method_t, method_list_t> Super;
public:
method_list_t **beginCategoryMethodLists() {
return beginLists();
}
method_list_t **endCategoryMethodLists(Class cls);
method_array_t duplicate() {
return Super::duplicate<method_array_t>();
}
};
property_array_t
代码实现
class property_array_t :
public list_array_tt<property_t, property_list_t>
{
typedef list_array_tt<property_t, property_list_t> Super;
public:
property_array_t duplicate() {
return Super::duplicate<property_array_t>();
}
};
protocol_array_t
代码实现
class protocol_array_t :
public list_array_tt<protocol_ref_t, protocol_list_t>
{
typedef list_array_tt<protocol_ref_t, protocol_list_t> Super;
public:
protocol_array_t duplicate() {
return Super::duplicate<protocol_array_t>();
}
};
list_array_tt
代码实现
class list_array_tt {
struct array_t {
uint32_t count;
List* lists[0];
static size_t byteSize(uint32_t count) {
return sizeof(array_t) + count*sizeof(lists[0]);
}
size_t byteSize() {
return byteSize(count);
}
};
protected:
class iterator {
List **lists;
List **listsEnd;
typename List::iterator m, mEnd;
public:
iterator(List **begin, List **end)
: lists(begin), listsEnd(end)
{
if (begin != end) {
m = (*begin)->begin();
mEnd = (*begin)->end();
}
}
const Element& operator * () const {
return *m;
}
Element& operator * () {
return *m;
}
bool operator != (const iterator& rhs) const {
if (lists != rhs.lists) return true;
if (lists == listsEnd) return false; // m is undefined
if (m != rhs.m) return true;
return false;
}
const iterator& operator ++ () {
assert(m != mEnd);
m++;
if (m == mEnd) {
assert(lists != listsEnd);
lists++;
if (lists != listsEnd) {
m = (*lists)->begin();
mEnd = (*lists)->end();
}
}
return *this;
}
};
private:
union {
List* list;
uintptr_t arrayAndFlag;
};
bool hasArray() const {
return arrayAndFlag & 1;
}
array_t *array() {
return (array_t *)(arrayAndFlag & ~1);
}
void setArray(array_t *array) {
arrayAndFlag = (uintptr_t)array | 1;
}
public:
uint32_t count() {
uint32_t result = 0;
for (auto lists = beginLists(), end = endLists();
lists != end;
++lists)
{
result += (*lists)->count;
}
return result;
}
iterator begin() {
return iterator(beginLists(), endLists());
}
iterator end() {
List **e = endLists();
return iterator(e, e);
}
uint32_t countLists() {
if (hasArray()) {
return array()->count;
} else if (list) {
return 1;
} else {
return 0;
}
}
List** beginLists() {
if (hasArray()) {
return array()->lists;
} else {
return &list;
}
}
List** endLists() {
if (hasArray()) {
return array()->lists + array()->count;
} else if (list) {
return &list + 1;
} else {
return &list;
}
}
void attachLists(List* const * addedLists, uint32_t addedCount) {
if (addedCount == 0) return;
if (hasArray()) {
// many lists -> many lists
uint32_t oldCount = array()->count;
uint32_t newCount = oldCount + addedCount;
setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
array()->count = newCount;
memmove(array()->lists + addedCount, array()->lists,
oldCount * sizeof(array()->lists[0]));
memcpy(array()->lists, addedLists,
addedCount * sizeof(array()->lists[0]));
}
else if (!list && addedCount == 1) {
// 0 lists -> 1 list
list = addedLists[0];
}
else {
// 1 list -> many lists
List* oldList = list;
uint32_t oldCount = oldList ? 1 : 0;
uint32_t newCount = oldCount + addedCount;
setArray((array_t *)malloc(array_t::byteSize(newCount)));
array()->count = newCount;
if (oldList) array()->lists[addedCount] = oldList;
memcpy(array()->lists, addedLists,
addedCount * sizeof(array()->lists[0]));
}
}
void tryFree() {
if (hasArray()) {
for (uint32_t i = 0; i < array()->count; i++) {
try_free(array()->lists[i]);
}
try_free(array());
}
else if (list) {
try_free(list);
}
}
template<typename Result>
Result duplicate() {
Result result;
if (hasArray()) {
array_t *a = array();
result.setArray((array_t *)memdup(a, a->byteSize()));
for (uint32_t i = 0; i < a->count; i++) {
result.array()->lists[i] = a->lists[i]->duplicate();
}
} else if (list) {
result.list = list->duplicate();
} else {
result.list = nil;
}
return result;
}
};