zoukankan      html  css  js  c++  java
  • ios-动态添加方法,交换方法,重定向方法

      新建一个类Person,Person.h 不写代码,Person.m 有如下两个方法:

    - (void)eat
    {
        NSLog(@"xxx eat====");
    }

    【动态添加方法】

      尝试在 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;
    }

      然后调用运行和打印如下:

    Person *p = [Person new];
    [p performSelector:@selector(run:) withObject:@"222xxxxxxxxxxx"]; // log: xxx run==222xxxxxxxxxxx

      在 ios调用私有方法 中有提到如何打印一个类下的方法 ,这里调用测试如下

        [self getMethods];
        
        Person *p = [Person new];
        [p performSelector:@selector(run:) withObject:@"222xxxxxxxxxxx"];
        
        [self getMethods];

      打印如下:

    =============0
    方法名= eat
    参数类型= @
    参数类型= :
    返回类型值类型= v
    xxx run==222xxxxxxxxxxx
    =============0
    方法名= run:
    参数类型= @
    参数类型= :
    参数类型= @
    返回类型值类型= v
    =============1
    方法名= eat
    参数类型= @
    参数类型= :
    返回类型值类型= v

      从上面这个打印也可以看出,当没有调用这个方法时,打印 Person 类下方法只有eat一个;当调用了 run 方法后,这个方法就被添加到 Person 类的 methodlist 里了。

    【交换方法】

      在 Person.m 中加一个 -sleep 方法

    - (void)eat
    {
        NSLog(@"xxx eat====");
    }
    
    - (void)sleep
    {
        NSLog(@"xxx sleep===");
    }

      可以在 Person 的 + load 方法中进行方法交换,因为一个类的 +load 方法在该类载入内存时就会开始调用。

    + (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====
  • 相关阅读:
    PRML 读书记录
    What’s the difference between Taxonomies and Ontologies? Ask Dr. Search
    C#中IP地址转换为数值的方法
    [转]读《简约至上》有感 及我的支语片言
    读《一名毕业生的程序员之路》有感
    [转载]温故知新 javascript 正则表达式
    [转]jQuery 1.9 移除了 $.browser 的替代方法
    QQ网盘首页,这样也能上线!做产品的人是白痴啊!
    [转]P3P解决cookie存取的跨域问题
    【转】跨浏览器“复制到粘贴板”JavaScript代码
  • 原文地址:https://www.cnblogs.com/buerjj/p/8546209.html
Copyright © 2011-2022 走看看