美文网首页
RUNTime操作基础

RUNTime操作基础

作者: One苹果OneDay | 来源:发表于2016-07-28 21:28 被阅读44次

    runtime是OC比较底层的东西,而我们在学OC的时候很容易忽视runtime的学习,但是runtime的熟悉还是很有必要的,他可以使你更了解底层的封装,从而对OC的理解更加深入(比如成员变量的本质就是一个结构体)

    1.关于成员变量
    首先建一个类,加入叫Person,在类下面导入runtime框架

    #import <objc/runtime.h>
    

    在这里首先介绍下runtime关于成员的相关属性
    Ivar *class_copyIvarList(Class cls, unsigned int *outCount) //获取所有成员变量
    const char *ivar_getName(Ivar v) //获取某个成员变量的名字
    const char *ivar_getTypeEncoding(Ivar v) //获取某个成员变量的类型编码
    Ivar class_getInstanceVariable(Class cls, const char *name) //获取某个类中指定名称的成员变量
    id object_getIvar(id obj, Ivar ivar) //获取某个对象中的某个成员变量的值
    void object_setIvar(id obj, Ivar ivar, id value) //设置某个对象的某个成员变量的值
    我们来操作一下
    首先创建成员变量

    @property(nonatomic,strong)NSString * name;
    @property(nonatomic,strong)NSString * gender;
    @property(nonatomic,assign)NSNumber* age;
    @property(nonatomic,assign)NSInteger height;
    

    ①利用runtime得到成员变量的属性

    -(NSString*)description
    {
       
        unsigned int outCount;
        //获取所有的成员变量
        //class 要获取的某个类名,outCount:通过这一个函数执行之后将成员变量的个数赋值到此
        Ivar *ivarList = class_copyIvarList([Person class], &outCount);
    
        for (NSInteger i = 0; i < outCount; i++) {
            //每次获取一个成员变量
            Ivar ivar = ivarList[i];
    
            //打印成员变量的名字和编码类型
            NSLog(@"name = %s,type = %s",ivar_getName(ivar),ivar_getTypeEncoding(ivar));
        }
        return nil;
    }
    

    ②利用runtime给成员变量赋值
    首先在Person.h文件定义一个方法

    + (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age height:(NSInteger)height;
    

    在Person.m文件实现

    + (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age height:(NSInteger)height
    {
        Person *person = [Person new];
        unsigned int outCount;
        Ivar *ivarList = class_copyIvarList(self,&outCount);
    
        //obj:要设置的对象,   ivar:压迫设置的对象的某一个属性  value:value
        object_setIvar(person,ivarList[0],name);
        object_setIvar(person,ivarList[1],gender);
        object_setIvar(person,ivarList[2],age);
        object_setIvar(person,ivarList[3],@(height));
    
    
        return person;
    }
    

    ③得到成员变量的值
    在person.h里设置方法

    - (void)getPersonMessager;
    

    在Person.m里实现

    - (void)getPersonMessager
    {
        unsigned int outCount;
        Ivar *ivarList = class_copyIvarList([Person class], &outCount);
        for (NSInteger i = 0; i < outCount; i++) {
    
            NSLog(@"name = %s,value = %@",ivar_getName(ivarList[i]),object_getIvar(self, ivarList[i]));
    
        }
    
    }
    

    2.关于实例方法
    runtime的属性:
    1 + resolveInstanceMethod:(SEL)sel // 为一个实例方法动态添加实现
    2 + resolveClassMethod:(SEL)sel // 为一个类方法动态添加实现
    3 - (id)forwardingTargetForSelector:(SEL)aSelector
    //为没有实现的方法指定一个对象
    4 - (void)forwardInvocation:(NSInvocation *)anInvocation
    //子类重载这个方法为消息指定其他对象

    具体的用法

    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
    
        NSString *selString = NSStringFromSelector(sel);
    
        if ([selString isEqualToString:@"walkOnTheStreet:"]) {
    
            //为一个没有实现的方法是动态添加实现
    
             cls:类
             name:没有实现的方法
             IMP:要添加的实现
             types:动态添加的实现的类型编码
    
    
            class_addMethod(self, @selector(walkOnTheStreet:), (IMP)walkFunc, "V@:@");
    
            //Void 对应类型编码V ,对象类型是 @
        }
        return [super resolveInstanceMethod:sel];
    
    }
    

    ②切换消息转化对象:把Person的方法转移到Dog里实现
    在Person里设置方法

    - (void)walkOnTheStreet1
    

    在Dog里定义一个一样的方法

    - (void)walkOnTheStreet1
    

    在Dog.m里实现

    - (void)walkOnTheStreet1
    {
        NSLog(@"you are dog!!!!!!--%s",__func__);
    }
    

    在Person.m里转移
    方法1

    - (void)orwardInvocation:(NSInvocation *)anInvocation
    {
        //判断Dog显影方法
        if ([Dog instancesRespondToSelector:anInvocation.selector]) {
            self.dog= [Dog new];
            [anInvocation invokeWithTarget:self.dog];//taget
        }
    
    }
    

    方法1

    //给方法1指定一个有效的签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
        if (!methodSignature) {
            methodSignature = [Dog instanceMethodSignatureForSelector:aSelector];
        }
    
        return methodSignature;
    
    }
    
    

    方法2

    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
    
        NSString *selString = NSStringFromSelector(aSelector);
    
        if ([selString isEqualToString:@"walkOnTheStreet1"]) {
            self.dog = [Dog new];
    
            return self.dog;
            
    
    
        }
    
        //如果方法没有响应
        return [super forwardingTargetForSelector:aSelector];
    
    }
    

    相关文章

      网友评论

          本文标题:RUNTime操作基础

          本文链接:https://www.haomeiwen.com/subject/efnajttx.html