一直对 ios 类 OC/Swift 的类本质理解总感觉是模糊的,好像知道但又不是特别清楚,周末花一些时间整理备忘。
一. 错误版本: runtime.h中 objc_class 的定义(Objc2 已经弃用, 此版本也是网上分析源码用的最多的一种,需警惕!)
#if !OBJC_TYPES_DEFINED
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;
/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;
/// An opaque type that represents a category.
typedef struct objc_category *Category;
/// An opaque type that represents an Objective-C declared property.
typedef struct objc_property *objc_property_t;
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;
/* Use `Class` instead of `struct objc_class *` */
#endif
(看起来确实简单明了,然并卵)
------------------------------------黄金分割线------------------------------------
二. 正确版本
源码 objc-private.h 文件中定义如下:
typedef struct objc_class *Class;
typedef struct objc_object *id;
源码 objc-runtime-new.h 中关于 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
class_rw_t *data() {
return bits.data();
}
...
};
//swift 类
struct swift_class_t : objc_class {
uint32_t flags;
uint32_t instanceAddressOffset;
uint32_t instanceSize;
uint16_t instanceAlignMask;
uint16_t reserved;
uint32_t classSize;
uint32_t classAddressOffset;
void *description;
// ...
void *baseAddress() {
return (void *)((uint8_t *)this - classAddressOffset);
}
};
类肯定有对应的成员变量列表,属性列表,协议列表,它们在哪里?
在 Objc2.0 中,存储位置在 class_rw_t 中,其中的 class_ro_t 理解是类常规定义的部分,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;
...
};
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;
}
};
分类在哪里?我还要靠它提高工作效率呢?
继续阅读源码 objc-runtime-new.h 文件发现方法:
static void addUnattachedCategoryForClass(category_t *cat, Class cls,
header_info *catHeader)
{
runtimeLock.assertWriting();
// DO NOT use cat->cls! cls may be cat->cls->isa instead
NXMapTable *cats = unattachedCategories();
category_list *list;
list = (category_list *)NXMapGet(cats, cls);
if (!list) {
list = (category_list *)
calloc(sizeof(*list) + sizeof(list->list[0]), 1);
} else {
list = (category_list *)
realloc(list, sizeof(*list) + sizeof(list->list[0]) * (list->count + 1));
}
list->list[list->count++] = (locstamped_category_t){cat, catHeader};
NXMapInsert(cats, cls, list);
}
struct locstamped_category_t {
category_t *cat;
struct header_info *hi;
};
struct locstamped_category_list_t {
uint32_t count;
#if __LP64__
uint32_t reserved;
#endif
locstamped_category_t list[0];
};
struct category_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta) {
if (isMeta) return nil; // classProperties;
else return instanceProperties;
}
};
又看到了熟悉的老朋友:
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
至此,我们基本清楚了 objc_class 的结构,对应的成员变量,属性,方法,协议列表的存储变量;以及category 的存储;
网友评论