• ios-runtime


    git下载地址:git@github.com:lu459700780/RunTime.git

    viewController.h

    #import <UIKit/UIKit.h>
    @interface ViewController : UIViewController
    
    @property(nonatomic,strong)NSString *hello;
    @property(nonatomic,strong)NSString *hello1;
    
    /**
     *  交换方法使用
     */
    - (void)method1;
    - (void)method2;
    
    @end

    viewController.m

    #import "ViewController.h"
    #import "RunTime.h"
    #import "RunTime+Category.h"
    
    //项目下载地址:git@github.com:lu459700780/RunTime.git
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    -(NSString *)description{
        return [NSString stringWithFormat:@"hello:%@",_hello];
    }
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            _hello = @"hello";
        }
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.view.backgroundColor = [UIColor whiteColor];
        _hello = @"hello";
        
        
        //获取某一个类所有属性和所有方法
        [RunTime getAllPropertyAndAllMethod:[ViewController class]];
        //改变某一属性值
        [RunTime changeVariable];
        //增加新方法
        [RunTime addNewMethod];
        //交换方法
        [RunTime exchangeMethod];
        
        //增加新属性
        RunTime *keytool = [[RunTime alloc]init];
        keytool.newVariable = @"Hello";
        keytool.height = 100;
        NSLog(@"%@",[keytool newVariable]);
        NSLog(@"%f",[keytool height]);
    
        
    }
    
    
    - (void)method1
    {
        NSLog(@"method1");
    }
    - (void)method2
    {
        NSLog(@"method2");
    }
    
    
    @end

    RunTime.h

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface RunTime : NSObject
    
    /**
     *  获取所有成员变量和方法
     *
     *  @param myClass 类别
     */
    + (void)getAllPropertyAndAllMethod:(id)myClass;
    
    /**
     *  改变属性值
     */
    + (void)changeVariable;
    /**
     *  增加新方法
     */
    + (void)addNewMethod;
    /**
     *  交换方法
     */
    + (void)exchangeMethod;
    
    
    
    @end

    RunTime.m

    #import "RunTime.h"
    #import <objc/runtime.h>
    #import "ViewController.h"
    //获取屏幕宽度的宏
    #define ScreenWidth ([[UIScreen mainScreen] bounds].size.width)
    
    
    @implementation RunTime
    
    + (void)getAllPropertyAndAllMethod:(id)myClass
    {
        unsigned int outCount = 0;
        // 获取到所有的成员变量列表
        Ivar *vars = class_copyIvarList([myClass class], &outCount);
        // 遍历所有的成员变量
        for (int i = 0; i < outCount; i++) {
            Ivar ivar = vars[i]; // 取出第i个位置的成员变量
            
            const char *propertyName = ivar_getName(ivar); // 获取变量名
            const char *propertyType = ivar_getTypeEncoding(ivar); // 获取变量编码类型
            printf("变量名%s/变量编码类型%s
    ", propertyName, propertyType);
           
        }
        
        unsigned int count;
        //获取方法列表,所有在.m文件显式实现的方法都会被找到,包括setter+getter方法;
        Method *allMethods = class_copyMethodList([myClass class], &count);
        for(int i =0;i<count;i++)
        {
            //Method,为runtime声明的一个宏,表示对一个方法的描述
            Method md = allMethods[i];
            //获取SEL:SEL类型,即获取方法选择器@selector()
            SEL sel = method_getName(md);
            //得到sel的方法名:以字符串格式获取sel的name,也即@selector()中的方法名称
            const char *methodname = sel_getName(sel);
            NSLog(@"(Method:%s)",methodname);
        }
        
        
    }
    
    + (void)changeVariable
    {
        ViewController *viewVC = [[ViewController alloc]init];
        NSLog(@"改变前的viewVC里面的属性:%@",viewVC);
        
        unsigned int count = 0;
        Ivar *vars = class_copyIvarList([ViewController class], &count);
        Ivar ivv = vars[0]; //从第一个方法getAllVariable中输出的控制台信息,我们可以看到实例属性。
        object_setIvar(viewVC, ivv, @"world"); //属性被强制改为world。
        
        NSLog(@"改变之后的viewVC里面的属性:%@",viewVC);
        
    }
    
    + (void)addNewMethod
    {
        /* 动态添加方法:
         第一个参数表示Class cls 类型;
         第二个参数表示待调用的方法名称;
         第三个参数(IMP)addingMethod,IMP一个函数指针,这里表示指定具体实现方法addingMethod;
         第四个参数表方法的参数,0代表没有参数;
         */
        
        Method newMethod = class_getInstanceMethod(self, @selector(myNewMethod));
        
        ViewController *viewVC = [[ViewController alloc]init];
        
        class_addMethod([viewVC class], @selector(myNewMethod), method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
        //调用方法
        [viewVC performSelector:@selector(myNewMethod) withObject:nil];
    }
    
    - (void)myNewMethod
    {
        
        NSLog(@"addNewMethod");
    }
    //具体的实现(方法的内部都默认包含两个参数Class类和SEL方法,被称为隐式参数。)
    int addingMethod(id self, SEL _cmd){
        NSLog(@"已新增方法:myNewMethod");
        
        return 1;
    }
    
    + (void)exchangeMethod
    {
        ViewController *viewVC = [[ViewController alloc]init];
        
        Method method1 = class_getInstanceMethod([viewVC class], @selector(method1));
        Method method2 = class_getInstanceMethod([viewVC class], @selector(method2));
        
        //交换方法
        method_exchangeImplementations(method1, method2);
        
        [viewVC method1];
    }
    
    
    
    @end

      RunTime+Category.h

    #import "RunTime.h"
    @interface RunTime (Category)
    
    
    /**
     *  增加属性(字符串类型)
     */
    @property (nonatomic,strong)NSString *newVariable;
    /**
     *  增加属性(常量)
     */
    @property (nonatomic,assign)float height;
    
    
    @end

     RunTime+Category.m

    #import "RunTime+Category.h"
    #import <objc/runtime.h> //runtime API的使用需要包含此头文件
    
    //增加多个属性,key值不能一样
    const char * keytool = "keytool"; //做为key,字符常量 必须是C语言字符串;
    const char * keytool2 = "keytool2"; //做为key,字符常量 必须是C语言字符串;
    
    @implementation RunTime (Category)
    
    /**
     *  添加新属性
     *
     *  @param newVariable 新属性名
     */
    -(void)setNewVariable:(NSString *)newVariable{
        
        NSString *newStr = [NSString stringWithFormat:@"%@",newVariable];
        /*
         第一个参数是需要添加属性的对象;
         第二个参数是属性的key;
         第三个参数是属性的值;
         第四个参数是一个枚举值,类似@property属性创建时设置的关键字,可从命名看出各含义
         */
        objc_setAssociatedObject([RunTime class],keytool, newStr, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    /**
     *  提取属性的值
     *
     *  @return 属性值
     */
    -(NSString *)newVariable{
        NSString *myNewVariable = objc_getAssociatedObject([RunTime class], keytool);
        return myNewVariable;
    }
    
    /**
     *  添加新属性
     *
     *  @param height 新属性名
     */
    -(void)setHeight:(float)height{
        NSNumber *num = [NSNumber numberWithFloat:height];
        /*
         第一个参数是需要添加属性的对象;
         第二个参数是属性的key;
         第三个参数是属性的值;
         第四个参数是一个枚举值,类似@property属性创建时设置的关键字,可从命名看出各含义
         */
        objc_setAssociatedObject([RunTime class],keytool2, num, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    /**
     *  提取属性的值
     *
     *  @return 属性值
     */
    -(float)height{
        NSNumber *number = objc_getAssociatedObject([RunTime class], keytool2);
        return [number floatValue];
    }
    
    @end
  • 相关阅读:
    background之你不知道的background-position
    ES6学习笔记(二)
    ES6学习笔记(一)
    将博客搬至CSDN
    Mongodb的性能优化问题
    使用AngularJS实现的前后端分离的数据交互过程
    输出JS代码中的变量内容
    程序生成word与PDF文档的方法(python)
    python 2.7安装某些包出现错误:"libxml/xmlversion.h:没有那个文件或目录"
    Linux中安装配置spark集群
  • 原文地址:https://www.cnblogs.com/sayimba/p/6289393.html
Copyright © 2020-2023  润新知