ios-動態添加方法,交換方法,重定向方法

  新建一個類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====
相關文章
相關標籤/搜索