一个对象的方法像这样[obj doing]
,编译器转成消息发送objc_msgSend(obj, doing)
,Runtime时执行的流程是这样的:
(1)通过obj
的isa
指针找到它的class
;
(2)在class
的method list
找doing
(直接在cache
里找到,避免去遍历objc_method_list
);
(3)如果class
中没到doing
,继续往它的superclass
中找 ;
(4)一旦找到doing
这个函数,就去执行它的实现IMP
。
实例:isa指针指向的结构体创建,类对象的isa指针指向的我们称之为元类(metaclass),
元类中保存了创建类对象以及类方法所需的所有信息。
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY; // isa指针
};
类对象:Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY; // isa指针
#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_method_list {
struct objc_method_list *obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
方法:方法表示能够独立完成一个功能的一段代码
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE; // 方法名
char *method_types OBJC2_UNAVAILABLE; // 方法类型
IMP method_imp OBJC2_UNAVAILABLE; // 方法实现
}
SEL:
(1)SEL
是selecto
r在Objective-C
中的表示类型(Swift中是Selector类)。selector
是方法选择器,可以理解为区分方法的ID
,而这个ID
的数据结构是SEL
。
(2)selector
是SEL
的一个实例。
(3)selector
就是个映射到方法的C
字符串,你可以用Objective-C
编译器命令@selector()
或者Runtime
系统的sel_registerName
函数来获得一个 SEL 类型的方法选择器。
(4)selector既然是一个string,命名规则有两条:同一个类,selector
不能重复;不同的类,selector
可以重复。
IMP
指向最终实现程序的内存地址的指针。
类缓存:加速消息分发,系统会对方法和对应的地址进行缓存
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE; // 缓存的size
unsigned int occupied OBJC2_UNAVAILABLE; // 当前被占用的数目(缓存以散列表的形式存在)
Method _Nullable buckets[1] OBJC2_UNAVAILABLE; // 用数组表示的hashtable(cache_entry类型,代表一个方法缓存)
};
方法缓存的类型
struct cache_entry {
SEL name; // 被缓存的方法名
void *unused; // 未被使用的保留字段
IMP imp; // 方法实现
};
Category:表示一个指向分类的结构体的指针
struct category_t {
const char *name; // class_name
classref_t cls; // 要扩展的类对象,编译时不定义,在运行时通过name对应到对应的类对象
struct method_list_t *instanceMethods; // 所有给类添加的实例方法的列表
struct method_list_t *classMethods; // 所有添加的类方法的列表
struct protocol_list_t *protocols; // 实现的所有协议的列表
struct property_list_t *instanceProperties; // 所有的properties(是我们可以通过objc_setAssociatedObject和objc_getAssociatedObject增加实例变量的原因)
};