id和Class
typedef struct objc_class *Class //Class是一个指向objc_class结构体的指针
typedef struct objc_object *id //id是一个指向objc_object结构体的指针
struct objc_object { //表示一个对象
Class isa OBJC_ISA_AVAILABILITY; //指向该对象所属的类(存放着成员变量和动态方法)
};
struct objc_class { //表示一个类
Class isa OBJC_ISA_AVAILABILITY;//指向该类的元数据(static成员变量和static方法(+))
#if !__OBJC2__
Class super_class //父类
const char *name //类名
long version //版本
long info //信息
long instance_size //实例变量大小
struct objc_ivar_list *ivars //变量
struct objc_method_list **methodLists //方法
struct objc_cache *cache //缓存(方法)
struct objc_protocol_list *protocols //协议
#endif
}
SEL
-
在OC中用selector表示,表示一个方法的选择器
typedef struct objc_selector *SEL struct objc_selector{ char *name; //名称 char *type; //类型 }
IMP
typedef id (*IMP)(id, SEL, ...); //指向函数的指针
Method
typedef struct objc_method *Method //代表着类中的某个方法的类型
struct objc_method {
SEL method_name //名称
char *method_types //类型
IMP method_imp //实现
}
IVar
typedef struct objc_ivar *Ivar;//对象中的变量
struct objc_ivar {
char *ivar_name //名称
char *ivar_type //类型
int ivar_offset //基地址偏移量
#ifdef __LP64__
int space //占用空间
#endif
}
Property
typedef struct objc_property *objc_property_t;//对象声明的属性
typedef struct {
const char *name; //名称
const char *value; //值(通常是空的)
} objc_property_attribute_t;
Cache
typedef struct objc_cache *Cache //方法缓存表
struct objc_cache {
unsigned int mask /* total = mask + 1 */
unsigned int occupied
Method buckets[1]
};
Category
typedef struct objc_category *Category; //一个类的扩展
struct objc_category {
char *category_name //扩展名
char *class_name //类名
struct objc_method_list *instance_methods //实例方法列表
struct objc_method_list *class_methods //类的方法列表
struct objc_protocol_list *protocols // 协议列表
} //扩展都是对方法的操作,所以不能添加属性
添加属性的方法:
objc_setAssociatedObject
objc_getAssociatedObject
objc_removeAssociatedObjects
消息(过程)
检测selector是不是要忽略
检测target是不是nil对象,对nil发送的消息都会被忽略掉
查找这个类的IMP,先从(isa指向的类的)Cache中查找,找到了就执行方法。(类方法会从metaclass中查找)
如果找不到就去方法分发表中查找,找不到就去父类中查找,直到NSObject
-
再找不到就去开始方法动态解析
- resolveInstanceMethod:决定是否动态添加方法
- forwardingTargetForSelector(重定向):指定哪个对象响应selector.指定self或者nil会进入第三步
- methodSignatureForSelector:指定方法签名,返回nil,不处理,否则进入下一步
- forwardInvocation(转发):修改方法,修改响应对象,不成功则进入下一步
- doesNotRecognizeSelector:没有实现就会crash
Method Swizzing
- 改变内置类的方法的实现
- Swizzling在load方法中实现
- 使用dispatch_once保证只交换一次