zoukankan      html  css  js  c++  java
  • ios runtime部分事例方法说明

    一.场景--动态改变变量

    unsigned int count = 0;
        Ivar *ivar = class_copyIvarList([self.person class], &count);
        for (int i = 0; i<count; i++) {
            Ivar var = ivar[i];
            const char *varName = ivar_getName(var);
            NSString *proname = [NSString stringWithUTF8String:varName];
            
            if ([proname isEqualToString:@"_name"]) {   //这里别忘了给属性加下划线
                object_setIvar(self.person, var, @"daming");
                break;
            }
        }
        NSLog(@"XiaoMing change name  is %@",self.person.name);
        self.textfield.text = self.self.person.name;

    方法说明:

    1.Ivar *class_copyIvarList(Class cls, unsigned int *outCount) 

      用法:返回类的所有属性和变量
      参数:class   类型
          outCount  类型的数目

      返回:Ivar 指针 当做组来用

      拓展:class_copyPropertyList  返回对象类的属性(@property申明的属性)

    2.const char *ivar_getName(Ivar v)

     用法: 返回实例变量的名称。

     拓展:ivar_getOffset: 返回实例变量的偏移量。

          ivar_getTypeEncoding:返回实例变量的类型字符串。

    3. void object_setIvar(id obj, Ivar ivar, id value)

     用法:修改类型的变量

     参数:obj  所选类

        ivar 实例变量

        value  更改变量

     拓展:id object_getIvar(id obj, Ivar ivar)  获取类实例的变量

    二、场景--添加方法

    class_addMethod([self.person class], @selector(guess), (IMP)guessAnswer, "v@:");
        if ([self.person respondsToSelector:@selector(guess)]) {
            //Method method = class_getInstanceMethod([self.xiaoMing class], @selector(guess));
            [self.person performSelector:@selector(guess)];
            
        } else{
            NSLog(@"Sorry,I don't know");
        }
        self.textview.text = @"beijing";

    1.BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)  //Adds a new method to a class with a given name and implementation.

     用法:为类添加一个方法

     参数:class  类

         SEL    方法选择器 相当于名字

         IMP    方法指针

         types  描述方法参数类型的字符数组

    说明:sel与方法指针名字可以不同 一个是名字 一个是指针地址

    三、场景--动态方法交换

        self.person = [Person new];
        
        NSLog(@"%@",_person.sayName);
        
        NSLog(@"%@",_person.saySex);
        
        Method m1 = class_getInstanceMethod([self.person class], @selector(sayName));
        Method m2 = class_getInstanceMethod([self.person class], @selector(saySex));
        
        method_exchangeImplementations(m1, m2);

    1.Method class_getInstanceMethod(Class cls, SEL name)
     用法:获取某类的方法(Method类)

     参数:class 类

        SEL 方法选择器

    2.void method_exchangeImplementations(Method m1, Method m2)
     用法:交换方法

     参数:Method 方法

    四、场景--替换方法

    //这里也可以使用 [self.person class],不过要先初始化
        Method m1 = class_getInstanceMethod([Person class], @selector(sayName));
        Method m2 = class_getInstanceMethod([Tool class], @selector(changeMethod));
        
        method_exchangeImplementations(m1, m2);

    用法说过了,嗯!

    五:场景--方法上增加额外功能

    + (void)load {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class selfClass = [self class];
            
            SEL oriSEL = @selector(sendAction:to:forEvent:);
            Method oriMethod = class_getInstanceMethod(selfClass, oriSEL);
            
            SEL cusSEL = @selector(mySendAction:to:forEvent:);
            Method cusMethod = class_getInstanceMethod(selfClass, cusSEL);
            
            BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod));
            if (addSucc) {
                class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
            }else {
                method_exchangeImplementations(oriMethod, cusMethod);
            }
            
        });
    }
    - (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
        [[Tool sharedManager] addCount];
        [self mySendAction:action to:target forEvent:event];
    }

    说明:在程序运行时,Runtime会将所有的Class和Category加载到内存中,这时,会调用类的load方法,通知我们Class或Category已经被加载到内存中。

        代码逻辑:交换了方法 ,执行逻辑就改变了 :mySendAction触发->再次调用转到原有sendAction方法

    1. IMP method_getImplementation(Method m)

     用法:获取IMP

     拓展:const char *method_getTypeEncoding(Method m) 获取说明

         SEL method_getName(Method m)          获取name(SEL)

    2.IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)

     用法:Replaces the implementation of a method for a given class.


    注意:注销 free(ivars);

    参考资料来源:https://github.com/Tuccuay/RuntimeSummary

  • 相关阅读:
    gitlab备份及恢复
    Nginx一:常用命令和配置文件介绍
    SpringTask三:使用SpringBoot
    SpringTask二:注解配置方式
    SpringTask一:xml配置方式
    大坑!maven的web项目初始化错误:sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification ...
    Quartz(5):quartz监听器
    Quartz(4):quartz.properties配置文件介绍
    Quartz(3):simpleTrigger和cronTrigger触发器的介绍
    Quartz(2):JobDetail、JobExectionContext、JobDataMap的介绍
  • 原文地址:https://www.cnblogs.com/chaochaobuhuifei55/p/6709905.html
Copyright © 2011-2022 走看看