zoukankan      html  css  js  c++  java
  • runtime基础

    viewcontroller:

    #import "ViewController.h"
    
    #import <objc/runtime.h>
    
    
    #import <objc/message.h>
    @interface ViewController ()<UITableViewDataSource>{
        NSArray *_property0;
        NSArray *property1;
    }
    @property (nonatomic,strong)UIColor *property2;
    
    @property (nonatomic,strong)NSArray *property0;
    @end
    
    @implementation ViewController

    -(void)method0{
        NSLog(@">>>>>>>>5");
    }
    -(void)method1{
        NSLog(@">>>>>>>>6");
    }

    动态添加变量

    -(void)getAndSet{
        //添加--为动态创建类添加变量
        /**
         * 1.只能给动态创建的类添加变量也就是用 objc_allocateClassPair 创建的类
         * 2.添加变量只能在函数 objc_allocateClassPair 和 class_getInstanceVariable 之间添加才有效
         */
        Class CreatClass0 = objc_allocateClassPair([NSObject class], "CreatClass0", 0);
        class_addIvar(CreatClass0, "_attribute0", sizeof(NSString *), log(sizeof(NSString *)), "i");
    
        Ivar ivar = class_getInstanceVariable(CreatClass0, "_attribute0");//获取变量,如果没获取到说明不存在
        NSLog(@">>>>>>>>0:%@",[NSString stringWithUTF8String:ivar_getName(ivar)]);
        objc_registerClassPair(CreatClass0);
        NSLog(@"
    ");
        
        
        //添加--为动态创建的类添加变量然后添加属性,类和变量和属性都是动态创建的
        /**
         * 1.各个属性:暂时不知道
         * 2.下面这个反驳了上面的第二标,这个证明id不是不会报错,规律是如果id调用的是系统的类的方法,那么就不会报错,
         详细介绍:上面的@selector(name) 和 @selector(setName:) name是好多系统类都有方法,所以id会认为本身代表的是那个类
         所以不会报错,但是如果你硬写一个完全没有的方法,它就会报错
         * 3.添加属性不用再objc_registerClassPair之前,因为添加属性其实就是添加变量的set 和 get方法而已
         * 4.添加的属性和变量不能用kvc设置值和取值
         */
        
        objc_property_attribute_t type2 = { "T", "@"NSString"" };//"T"表示获取该属性的类型
        //  objc_property_attribute_t attribute2 = {"N",""};//value无意义时通常设置为空
        objc_property_attribute_t ownership2 = { "C", "" }; // C = copy
        objc_property_attribute_t backingivar2  = { "V", "_attribute0" };//
    
    
        objc_property_attribute_t attrs2[] = { type2, ownership2, backingivar2 };
        class_addProperty(CreatClass0, "_attribute0", attrs2, 3);
        
        SEL getter = NSSelectorFromString(@"attribute0");
        SEL setter = NSSelectorFromString(@"setAttribute0:");
        BOOL suc0 = class_addMethod(CreatClass0, getter, (IMP)attribute0Getter, "@@:");//i@:@ i:返回值类型int,若是v则表示void
        BOOL suc1 = class_addMethod(CreatClass0, setter, (IMP)attribute0Setter, "v@:@");//i@:@
        NSLog(@">>>>>>>>3:%@:%@",@(suc0),@(suc1));
        id idclass = [[CreatClass0 alloc]init];
        NSLog(@">>>>>>>>1:%@",[idclass performSelector:getter withObject:nil]);//withObject 传递的参数
        [idclass performSelector:setter withObject:@"为动态创建类先添加变量再添加属性"];
        NSLog(@">>>>>>>>2:%@",[idclass performSelector:getter withObject:nil]);
        //class获取--获取整个类的实例方法的方法列表
        /**
         *  1.获取所有实例方法,不包含静态方法
         *  2.不获取父类的方法
         *  3.隐式的get set 方法也能获取到
         *  4.关于Method的更多用法参考Class2类
         */
        unsigned int copycopyMethodListCount = 0;
        Method *methods = class_copyMethodList([self class], &copycopyMethodListCount);
        for (NSInteger i = 0; i < copycopyMethodListCount; i++) {
            Method method = methods[i];
            SEL name = method_getName(method);
    //        NSLog(@">>>>>>>>2:copyMethodList:%@",NSStringFromSelector(name));
        }
        free(methods);//释放
        NSLog(@"
    ");
        
        BOOL result0 = class_addProtocol([self class], NSProtocolFromString(@"UITableViewDelegate"));
        NSLog(@">>>>>>>>3:添加协议成功");
        //添加--协议
        /**
         * 1.class_addProtocol  参数含义:第一个:要添加协议的类,第二个:协议对象
         * 2.获取协议列表具体细节参照Class1里的内容
         */
        unsigned int copyProtocolListCount = 0;
        Protocol * __unsafe_unretained *protocals = class_copyProtocolList([self class], &copyProtocolListCount);
        for (NSInteger i = 0; i < copyProtocolListCount; i++) {
            Protocol * protocal = protocals[i];
            const char *name = protocol_getName(protocal);
            NSLog(@">>>>>>>>4:copyProtocolList:%s",name);
        }
        free(protocals);//释放
        NSLog(@"
    ");
    }
    
    //
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
    //    [self getAndSet];
    //    [self objectGetMethod];
    //    [self getClassCopy];
        [self method0];
        
        
        BOOL result0 = class_replaceMethod([self class], @selector(method0), [ViewController instanceMethodForSelector:NSSelectorFromString(@"method1")], NULL);
        NSLog(@">>>>>>>>2:%@",@(result0));
        [self method0];
        
    }
    
    
    //get方法
    NSString *attribute0Getter(id classInstance, SEL _cmd) {
        
        
        NSLog(@"%@    %@",classInstance,NSStringFromSelector(_cmd));
        Ivar ivar = class_getInstanceVariable([classInstance class], "_attribute0");//获取变量,如果没获取到说明不存在
        return object_getIvar(classInstance, ivar);
    }
    
    //set方法
    void attribute0Setter(id classInstance, SEL _cmd, NSString *newName) {
        Ivar ivar = class_getInstanceVariable([classInstance class], "_attribute0");//获取变量,如果没获取到说明不存在
        id oldName = object_getIvar(classInstance, ivar);
        if (oldName != newName) object_setIvar(classInstance, ivar, [newName copy]);
    }
    
    
    
    
    -(void)getClassCopy{
        
        //class获取--获取整个成员变量列表
        /**
         *  1.获取所有私有变量和属性
         *  2.获取的私有变量的名和定义的名一模一样
         *  3.获取的属性的名前面都添加了下划线
         */
        unsigned int copyIvarListCount = 0;
    
        Ivar *ivars = class_copyIvarList([self class], &copyIvarListCount);
        for (NSInteger i = 0; i< copyIvarListCount; i ++) {
            
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            NSLog(@">>>>>>>>0:class_copyIvarList:%s",name);
            
            
            
            
        }
        free(ivars);//释放
        NSLog(@"
    ");
        
        
        //获取属性列表(只获取属性不获取变量)
        //入参:类Class,int变量指针
        //返回:属性信息objc_property_t列表
        //*  1.获取所有属性
        //*  2.获取的属性名和你代码写的一样,获取出来的属性名不自动添加下划线
        //*  3.不能获取Category添加的属性。
        
        unsigned int property = 0;
        objc_property_t *objcProperty = class_copyPropertyList([self class], &property);
        for (NSInteger i = 0; i < property; i++) {
            objc_property_t propertyT = objcProperty[i];
            const char *name = property_getName(propertyT);
            NSLog(@">>>>>>>>0:class_copyIvarList:%s",name);
        }
        
        free(objcProperty);
        NSLog(@"
    ");
        
    
        //获取方法列表
        //入参:类Class,int变量指针
        //返回:方法信息Method列表
        //*  1.获取所有实例方法,不包含静态方法
        //*  2.不获取父类的方法
        //*  3.隐式的get set 方法也能获取到
        //*  4.可以获取分类和动态添加的方法。
    //    Method *class_copyMethodList(Class cls, unsigned int *outCount)
        
        unsigned int methodCount = 0;
        Method *methods = class_copyMethodList([self class], &methodCount);
        for(NSInteger i = 0 ; i < methodCount; i++){
            Method thod = methods[i];
            SEL name = method_getName(thod);
            NSLog(@"***:%@",NSStringFromSelector(name));
            ;
            
        }
        
        free(methods);
        
        NSLog(@"
    ");
        //添加--协议
        /**
         * 1.class_addProtocol  参数含义:第一个:要添加协议的类,第二个:协议对象
         * 2.获取协议列表具体细节参照Class1里的内容
         */
        unsigned int copyProtocolListCount = 0;
        Protocol * __unsafe_unretained *protocals = class_copyProtocolList([self class], &copyProtocolListCount);
        for (NSInteger i = 0; i < copyProtocolListCount; i++) {
            Protocol * protocal = protocals[i];
            const char *name = protocol_getName(protocal);
            NSLog(@">>>>>>>>3:copyProtocolList:%s",name);
        }
        free(protocals);//释放
        NSLog(@"
    ");
        
        
        
    }
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return 0;
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        return nil;
    }
    /*
     
     SEL:类成员方法的指针,但不同于C语言中的函数指针,函数指针直接保存了方法的地址,但SEL只是方法编号。
     IMP:一个函数指针,保存了方法的地址
     Method:方法的结构体,其中保存了方法的名字,实现和类型描述字符串
     
     //在runtime.h里面我们可以看到定义
     //Method 是一个方法结构体的指针
     typedef struct objc_method *Method;
     //方法的结构体包含了方法需要的信息
     struct objc_method {
       SEL method_name;
       char *method_types;//方法返回值,和各个参数类型等的字符串描述
       IMP method_imp;
     }
     //根据函数获取函数的SEL
     @selector()
     //获取函数指针SEL的函数名字符串
     NSString *NSStringFromSelector(SEL aSelector);
     //根据函数名获取函数指针
     SEL NSSelectorFromString(NSString *aSelectorName);
     //获取类Class的字符串描述
     NSString *NSStringFromClass(Class aClass);
     //根据类的字符串描述获取类Class
     Class _Nullable NSClassFromString(NSString *aClassName);
     //获取协议的字符串描述(协议名字)
     NSString *NSStringFromProtocol(Protocol *proto)
     //根据协议名字获取协议对象
     Protocol * _Nullable NSProtocolFromString(NSString *namestr)
     
     
     
     */
    
    #pragma mark objectGetMethod
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end

    获取对象方法

    -(void)objectGetMethod{
        //获取类名
        //入参:类Class
        //返回:类名char数组
        const char *result0 = class_getName([ViewController class]);
        NSLog(@">>>>>>>>0:%@",[NSString stringWithUTF8String:result0]);
        
        //获取父类
        //入参:类Class
        //返回:类Class
        Class result1 = class_getSuperclass([ViewController class]);
        NSLog(@">>>>>>>>1:%@",result1);
        
        //获取实例大小(返回size_t)
        //入参:实例的类Class
        //返回:大小size_t
        //深究请看这篇文章http://www.jianshu.com/p/df6b252fbaae
        size_t result2 = class_getInstanceSize([ViewController class]);
        NSLog(@">>>>>>>>2:%zu",result2);
        
        //获取类中指定名称实例成员变量的信息
        //入参:类Class,变量名
        //返回:变量信息Ivar
        //* 1.实例变量是指变量不是属性.例如某类有个属性为:username 那么它对应的实例变量为_username
        //* 2.这个方法可以获取属性的变量,也可以获取私有变量(这点很重要)
        //* 3.如果获取的变量为空,那么 ivar_getName和 ivar_getTypeEncoding 获取的值为空,那么[NSString stringWithUTF8String:ivar1Name] 执行崩溃
        const char *result3 = [@"property0" UTF8String];
        Ivar result4 = class_getInstanceVariable([ViewController class], result3);
        NSLog(@">>>>>>>>3:%@",result4);
        
        //获取指定的属性
        //入参:类Class,属性名char数组
        //返回:属性objc_property_t
        // *  1.属性不是变量,此方法只能获取属性
        // *  2.如果属性不存在那么返回的结构体为0(可以参考下面的判断)
        // *  3.属性不存在获取property_getName 和 property_getAttributes 会崩溃
        const char *result5 = [@"property0" UTF8String];
        objc_property_t result6 = class_getProperty([ViewController class], result5);
        NSLog(@">>>>>>>>4:%@",[NSString stringWithUTF8String:property_getName(result6)]);
        
        //获取方法实现
        //入参:类Class,方法名SEL
        //返回:方法实现IMP
        IMP result7 = class_getMethodImplementation([ViewController class], @selector(method0));
        result7();
        
        //获取方法实现
        //入参:类Class,方法名SEL
        //返回:方法实现IMP
        IMP result8 = class_getMethodImplementation_stret([ViewController class], @selector(method1));
        result8();
        
        //获取类方法
        //入参:类Class,方法名SEL
        //返回:方法Method
        Method result9 = class_getClassMethod([ViewController class], @selector(viewDidLoad));
        NSLog(@">>>>>>>>7:%@",result9);
    }
    
    OBJC_ASSOCIATION_RETAIN_NONATOMIC
    
    
    /*
     
     
     #import <objc/runtime.h>头文件
     
     //1 源对象alert
     //2 关键字 唯一静态变量key associatedkey
     //3 关联的对象 sender
     //4 关键策略  OBJC_ASSOCIATION_RETAIN_NONATOMIC
     
     associatedkey   associatedButtonkey是一个唯一静态变量
     objc_setAssociatedObject(alert, &associatedkey, message,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
     
     objc_setAssociatedObject(alert, &associatedButtonkey, sender,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
     
     
     
     
     NSString  *messageString =objc_getAssociatedObject(alertView, &associatedkey);
     
     
     UIButton *sender = objc_getAssociatedObject(alertView, &associatedButtonkey);
     
     
     objc_removeAssociatedObjects可以断开所有关联
     
     
     
     
     
     */
    
  • 相关阅读:
    NSURLConnection的异步请求方式
    <iOS>关于Xcode上的Other linker flags
    使用十六进制色值表示UIColor
    kubernetes & docker
    01 docker的安装与基本使用
    08 数组
    07 grep 正则
    06 信号处理和expect
    05 函数
    04 流程控制
  • 原文地址:https://www.cnblogs.com/hualuoshuijia/p/6801185.html
Copyright © 2011-2022 走看看