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====
  • 相关阅读:
    改造vant日期选择
    css3元素垂直居中
    npm综合
    (转)网页加水印方法
    Mac下IDEA自带MAVEN插件的全局环境配置
    隐藏注册控件窗口
    High performance optimization and acceleration for randomWalk, deepwalk, node2vec (Python)
    How to add conda env into jupyter notebook installed by pip
    The Power of WordNet and How to Use It in Python
    背单词app测评,2018年
  • 原文地址:https://www.cnblogs.com/buerjj/p/8546209.html
Copyright © 2011-2022 走看看