iOS -Runtime method

1.先來看一下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];
  };

里邊有三個類型別名,在這兒先解釋一下

SEL selector 的簡寫,俗稱方法選擇器,實(shí)質(zhì)存儲的是方法的名稱
IMP implement 的簡寫,俗稱方法實(shí)現(xiàn),看源碼得知它就是一個函數(shù)指針
Method 對上述兩者的一個包裝結(jié)構(gòu).

2.函數(shù)

method相關(guān)的函數(shù)也不是太多,下邊簡單羅列說明一下

//判斷類中是否包含某個方法的實(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)
//獲取類中的某個實(shí)例方法(減號方法)
Method class_getInstanceMethod(Class cls, SEL name)
//獲取類中的某個類方法(加號方法)
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ù)個數(shù)
unsigned int method_getNumberOfArguments(Method m)
//獲取返回值類型字符串
char *method_copyReturnType(Method m)
//獲取方法中第n個參數(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)
//注冊一個SEL
SEL sel_registerName(const char *str)
//判斷兩個SEL對象是否相同
BOOL sel_isEqual(SEL lhs, SEL rhs)

//通過塊創(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對象的sel方法
id objc_msgSend(id target, SEL sel, 參數(shù)列表...)
Showtime

3.下邊就來玩玩runtime API中的method相關(guān)操作

  //創(chuàng)建繼承自NSObject類的People類
  Class People = objc_allocateClassPair([NSObject class], "People", 0);
  //將People類注冊到runtime中
  objc_registerClassPair(People);
  //注冊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 @"返回值測試";
  });

  //向People類中添加 test:方法;函數(shù)簽名為@@:@,
  //    第一個@表示返回值類型為id,
  //    第二個@表示的是函數(shù)的調(diào)用者類型,
  //    第三個:表示 SEL
  //    第四個@表示需要一個id類型的參數(shù)
  class_addMethod(People, sel, imp, "@@:@");
  //替換People從NSObject類中繼承而來的description方法
  class_replaceMethod(People,@selector(description), imp_implementationWithBlock(^NSString*(id this,...){
      return @"我是Person類的對象";}),
      "@@:");

  //完成 [[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);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容