類對象中有類方法和實例方法的列表舒裤,列表中記錄著方法的名詞、參數(shù)和實現(xiàn)觉吭,而selector本質(zhì)就是方法名稱腾供,runtime通過這個方法名稱就可以在列表中找到該方法對應的實現(xiàn)。
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#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
} OBJC2_UNAVAILABLE;
這里聲明了一個指向struct objc_method_list指針的指針鲜滩,可以包含類方法列表和實例方法列表
在尋找IMP的地址時伴鳖,runtime提供了兩種方法
IMP class_getMethodImplementation(Class cls, SEL name);
IMP method_getImplementation(Method m)
第一種方法:class_getMethodImplementation
- (void)getIMP_class_getMethodImplementationFromSelector:(SEL)aSelector{
const char *className = object_getClassName([self class]);
// 獲取實例的IMP
IMP instanceIMP = class_getMethodImplementation(objc_getClass(className), aSelector);
// 獲取類的IMP
IMP classIMP = class_getMethodImplementation(objc_getMetaClass(className), aSelector);
NSLog(@"instanceIMP:%p classIMP:%p",instanceIMP,classIMP);
}
對于第一種方法而言,類方法和實例方法實際上都是通過調(diào)用class_getMethodImplementation()來尋找IMP地址的
第二種方法:method_getImplementation
- (void)getIMP_method_getImplementationFromSelector:(SEL)aSelector{
const char *className = object_getClassName([self class]);
// 獲取類中的某個實例方法
Method instanceMethod = class_getInstanceMethod(objc_getClass(className), aSelector);
// 獲取類中的某個類方法
Method classMethod = class_getClassMethod(objc_getClass(className), aSelector);
// 獲取實例的IMP
IMP instanceIMP = method_getImplementation(instanceMethod);
// 獲取類的IMP
IMP classIMP = method_getImplementation(classMethod);
NSLog(@"instanceIMP:%p classIMP:%p",instanceIMP,classIMP);
}
而method_getImplementation而言徙硅,傳入的參數(shù)只有method榜聂,區(qū)分類方法和實例方法在于封裝method的函數(shù)
類方法
Method class_getClassMethod(Class cls, SEL name)
實例方法
Method class_getInstanceMethod(Class cls, SEL name)
最后調(diào)用IMP method_getImplementation(Method m) 獲取IMP地址
方法列表中保存著下面方法的結構體,結構體中包含這方法的實現(xiàn)嗓蘑,selector本質(zhì)就是方法的名稱须肆,通過該方法名稱,即可在結構體中找到相應的實現(xiàn)桩皿。
struct objc_method {
SEL method_name
char *method_types
IMP method_imp
}