新建一個類Person,Person.h 不寫代碼,Person.m 有以下兩個方法:html
- (void)eat { NSLog(@"xxx eat===="); }
【動態添加方法】ios
嘗試在 Person 類裏添加一個 run 的實例方法。加上以下兩個方法便可:測試
void run(id self, SEL sel, NSString *str) { NSLog(@"xxx run==%@", str); } // 只要調用了該類未實現的方法,就會來到這個方法 + (BOOL)resolveInstanceMethod:(SEL)sel { BOOL isSucess = NO; if (sel == @selector(run:)) { isSucess = class_addMethod(self, sel, run, "v@:@"); } return isSucess; }
而後調用運行和打印以下:spa
Person *p = [Person new]; [p performSelector:@selector(run:) withObject:@"222xxxxxxxxxxx"]; // log: xxx run==222xxxxxxxxxxx
在 ios調用私有方法 中有提到如何打印一個類下的方法 ,這裏調用測試以下code
[self getMethods]; Person *p = [Person new]; [p performSelector:@selector(run:) withObject:@"222xxxxxxxxxxx"]; [self getMethods];
打印以下:orm
=============0 方法名= eat 參數類型= @ 參數類型= : 返回類型值類型= v xxx run==222xxxxxxxxxxx =============0 方法名= run: 參數類型= @ 參數類型= : 參數類型= @ 返回類型值類型= v =============1 方法名= eat 參數類型= @ 參數類型= : 返回類型值類型= v
從上面這個打印也能夠看出,當沒有調用這個方法時,打印 Person 類下方法只有eat一個;當調用了 run 方法後,這個方法就被添加到 Person 類的 methodlist 裏了。htm
【交換方法】blog
在 Person.m 中加一個 -sleep 方法內存
- (void)eat { NSLog(@"xxx eat===="); } - (void)sleep { NSLog(@"xxx sleep==="); }
能夠在 Person 的 + load 方法中進行方法交換,由於一個類的 +load 方法在該類載入內存時就會開始調用。get
+ (void)load { Method m1 = class_getInstanceMethod(self, @selector(sleep)); Method m2 = class_getInstanceMethod(self, @selector(eat)); method_exchangeImplementations(m1, m2); }
調用 run: 方法和打印以下: (從打印能夠發現,方法已經被替換了)
Person *p = [Person new];
[p performSelector:@selector(sleep)]; // log: xxx eat====
[p performSelector:@selector(eat)]; // log: xxx sleep===
【重定向方法】
在 Person.m 中 + load 方法以下: (意思是將sleep方法編號定向到eat方法的實現中)
+ (void)load { Method m1 = class_getInstanceMethod(self, @selector(sleep)); IMP imp = class_getMethodImplementation(self, @selector(eat)); method_setImplementation(m1, imp); }
調用打印以下:(能夠看到最終兩個方法都進入eat)
Person *p = [Person new]; [p performSelector:@selector(sleep)]; // log: xxx eat==== [p performSelector:@selector(eat)]; // log: xxx eat====