1.先來(lái)看一下method相關(guān)的定義
typedef struct objc_method *Method;
struct objc_method {
SEL method_name;
char *method_types;
IMP method_imp;
}
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;
}
struct objc_method_description {
SEL name; /**< The name of the method */
char *types; /**< The types of the method arguments */
};
struct objc_method_description_list {
int count;
struct objc_method_description list[1];
};
里邊有三個(gè)類型別名,在這兒先解釋一下
SEL selector 的簡(jiǎn)寫(xiě),俗稱方法選擇器,實(shí)質(zhì)存儲(chǔ)的是方法的名稱
IMP implement 的簡(jiǎn)寫(xiě),俗稱方法實(shí)現(xiàn),看源碼得知它就是一個(gè)函數(shù)指針
Method 對(duì)上述兩者的一個(gè)包裝結(jié)構(gòu).
2.函數(shù)
method相關(guān)的函數(shù)也不是太多,下邊簡(jiǎn)單羅列說(shuō)明一下
//判斷類中是否包含某個(gè)方法的實(shí)現(xiàn)
BOOL class_respondsToSelector(Class cls, SEL sel)
//獲取類中的方法列表
Method *class_copyMethodList(Class cls, unsigned int *outCount)
//為類添加新的方法,如果方法該方法已存在則返回NO
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
//替換類中已有方法的實(shí)現(xiàn),如果該方法不存在添加該方法
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
//獲取類中的某個(gè)實(shí)例方法(減號(hào)方法)
Method class_getInstanceMethod(Class cls, SEL name)
//獲取類中的某個(gè)類方法(加號(hào)方法)
Method class_getClassMethod(Class cls, SEL name)
//獲取類中的方法實(shí)現(xiàn)
IMP class_getMethodImplementation(Class cls, SEL name)
//獲取類中的方法的實(shí)現(xiàn),該方法的返回值類型為struct
IMP class_getMethodImplementation_stret(Class cls, SEL name)
//獲取Method中的SEL
SEL method_getName(Method m)
//獲取Method中的IMP
IMP method_getImplementation(Method m)
//獲取方法的Type字符串(包含參數(shù)類型和返回值類型)
const char *method_getTypeEncoding(Method m)
//獲取參數(shù)個(gè)數(shù)
unsigned int method_getNumberOfArguments(Method m)
//獲取返回值類型字符串
char *method_copyReturnType(Method m)
//獲取方法中第n個(gè)參數(shù)的Type
char *method_copyArgumentType(Method m, unsigned int index)
//獲取Method的描述
struct objc_method_description *method_getDescription(Method m)
//設(shè)置Method的IMP
IMP method_setImplementation(Method m, IMP imp)
//替換Method
void method_exchangeImplementations(Method m1, Method m2)
//獲取SEL的名稱
const char *sel_getName(SEL sel)
//注冊(cè)一個(gè)SEL
SEL sel_registerName(const char *str)
//判斷兩個(gè)SEL對(duì)象是否相同
BOOL sel_isEqual(SEL lhs, SEL rhs)
//通過(guò)塊創(chuàng)建函數(shù)指針,block的形式為^ReturnType(id self,參數(shù),...)
IMP imp_implementationWithBlock(id block)
//獲取IMP中的block
id imp_getBlock(IMP anImp)
//移出IMP中的block
BOOL imp_removeBlock(IMP anImp)
//調(diào)用target對(duì)象的sel方法
id objc_msgSend(id target, SEL sel, 參數(shù)列表...)
Showtime
3.下邊就來(lái)玩玩runtime API中的method相關(guān)操作
//創(chuàng)建繼承自NSObject類的People類
Class People = objc_allocateClassPair([NSObject class], "People", 0);
//將People類注冊(cè)到runtime中
objc_registerClassPair(People);
//注冊(cè)test: 方法選擇器
SEL sel = sel_registerName("test:");
//函數(shù)實(shí)現(xiàn)
IMP imp = imp_implementationWithBlock(^(id this,id args,...){
NSLog(@"方法的調(diào)用者為 %@",this);
NSLog(@"參數(shù)為 %@",args);
return @"返回值測(cè)試";
});
//向People類中添加 test:方法;函數(shù)簽名為@@:@,
// 第一個(gè)@表示返回值類型為id,
// 第二個(gè)@表示的是函數(shù)的調(diào)用者類型,
// 第三個(gè):表示 SEL
// 第四個(gè)@表示需要一個(gè)id類型的參數(shù)
class_addMethod(People, sel, imp, "@@:@");
//替換People從NSObject類中繼承而來(lái)的description方法
class_replaceMethod(People,@selector(description), imp_implementationWithBlock(^NSString*(id this,...){
return @"我是Person類的對(duì)象";}),
"@@:");
//完成 [[People alloc]init];
id p1 = objc_msgSend(objc_msgSend(People, @selector(alloc)),@selector(init));
//調(diào)用p1的sel選擇器的方法,并傳遞@"???"作為參數(shù)
id result = objc_msgSend(p1, sel,@"???");
//輸出sel方法的返回值
NSLog(@"sel 方法的返回值為 : %@",result);
//獲取People類中實(shí)現(xiàn)的方法列表
NSLog(@"輸出People類中實(shí)現(xiàn)的方法列表");
unsigned int methodCount;
Method * methods = class_copyMethodList(People, &methodCount);
for (int i = 0; i<methodCount; i++) {
NSLog(@"方法名稱:%s",sel_getName(method_getName(methods[i])));
NSLog(@"方法Types:%s",method_getDescription(methods[i])->types);
}
free(methods);