id和Class
typedef struct objc_class *Class //Class是一個(gè)指向objc_class結(jié)構(gòu)體的指針
typedef struct objc_object *id //id是一個(gè)指向objc_object結(jié)構(gòu)體的指針
struct objc_object { //表示一個(gè)對(duì)象
Class isa OBJC_ISA_AVAILABILITY; //指向該對(duì)象所屬的類(存放著成員變量和動(dòng)態(tài)方法)
};
struct objc_class { //表示一個(gè)類
Class isa OBJC_ISA_AVAILABILITY;//指向該類的元數(shù)據(jù)(static成員變量和static方法(+))
#if !__OBJC2__
Class super_class //父類
const char *name //類名
long version //版本
long info //信息
long instance_size //實(shí)例變量大小
struct objc_ivar_list *ivars //變量
struct objc_method_list **methodLists //方法
struct objc_cache *cache //緩存(方法)
struct objc_protocol_list *protocols //協(xié)議
#endif
}
SEL
-
在OC中用selector表示嘉赎,表示一個(gè)方法的選擇器
typedef struct objc_selector *SEL struct objc_selector{ char *name; //名稱 char *type; //類型 }
IMP
typedef id (*IMP)(id, SEL, ...); //指向函數(shù)的指針
Method
typedef struct objc_method *Method //代表著類中的某個(gè)方法的類型
struct objc_method {
SEL method_name //名稱
char *method_types //類型
IMP method_imp //實(shí)現(xiàn)
}
IVar
typedef struct objc_ivar *Ivar;//對(duì)象中的變量
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;//對(duì)象聲明的屬性
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; //一個(gè)類的擴(kuò)展
struct objc_category {
char *category_name //擴(kuò)展名
char *class_name //類名
struct objc_method_list *instance_methods //實(shí)例方法列表
struct objc_method_list *class_methods //類的方法列表
struct objc_protocol_list *protocols // 協(xié)議列表
} //擴(kuò)展都是對(duì)方法的操作,所以不能添加屬性
添加屬性的方法:
objc_setAssociatedObject
objc_getAssociatedObject
objc_removeAssociatedObjects
消息(過程)
檢測(cè)selector是不是要忽略
檢測(cè)target是不是nil對(duì)象婉刀,對(duì)nil發(fā)送的消息都會(huì)被忽略掉
查找這個(gè)類的IMP,先從(isa指向的類的)Cache中查找塘娶,找到了就執(zhí)行方法舀透。(類方法會(huì)從metaclass中查找)
如果找不到就去方法分發(fā)表中查找,找不到就去父類中查找衅鹿,直到NSObject
-
再找不到就去開始方法動(dòng)態(tài)解析
- resolveInstanceMethod:決定是否動(dòng)態(tài)添加方法
- forwardingTargetForSelector(重定向):指定哪個(gè)對(duì)象響應(yīng)selector.指定self或者nil會(huì)進(jìn)入第三步
- methodSignatureForSelector:指定方法簽名,返回nil过咬,不處理大渤,否則進(jìn)入下一步
- forwardInvocation(轉(zhuǎn)發(fā)):修改方法,修改響應(yīng)對(duì)象掸绞,不成功則進(jìn)入下一步
- doesNotRecognizeSelector:沒有實(shí)現(xiàn)就會(huì)crash
Method Swizzing
- 改變內(nèi)置類的方法的實(shí)現(xiàn)
- Swizzling在load方法中實(shí)現(xiàn)
- 使用dispatch_once保證只交換一次