美文网首页
Runtime初识

Runtime初识

作者: ZYZZZ | 来源:发表于2016-07-28 21:19 被阅读0次

    runtime的使用先导入runtime类

    #import <objc/runtime.h>
    

    runtime 可以对类操作
    举个例子
    先创建一个Person类
    在.h中声明方法

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

    在.m中使用

    #import "Person.h"
    #import <objc/runtime.h>
    
    @implementation Person
    /*
    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)    //设置某个对象的某个成员变量的值
    TypeEncoding:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
    */
    
    - (NSString *)description
    {
        // class:要获取的某个类,outCount:通过这一个函数执行之后会将成员变量的个数复制到此
        unsigned int outCount;
        Ivar *ivarList = class_copyIvarList([Person class], &outCount);
        for (NSInteger i = 0; i < outCount; i++) {
            // 每次获取一个成员变量
            Ivar ivar = ivarList[i];
            // 打印成员变量的类型编码
            NSLog(@"name = %s", ivar_getName(ivar));
            NSLog(@"type = %s", ivar_getTypeEncoding(ivar));
            
        }
        return nil;
    }
    
    + (Person *)personWithName:(NSString *)name gender:(NSString *)gender age:(NSNumber *)age weight:(NSInteger)weight
    {
        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], @(weight));
        
        return person;
    }
    
    - (void)getPersonMessage
    {
        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]));
        }
    }
    
    // 编码
    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
        unsigned int outCount;
        Ivar *ivarList = class_copyIvarList([Person class], &outCount);
        for (NSInteger i = 0; i < outCount; i++) {
            const char *cName = ivar_getName(ivarList[i]);
            NSString *name = [NSString stringWithUTF8String:cName];
            
            [aCoder encodeObject:[self valueForKey:name] forKey:name];
        
        }
    }
    
    // 解码
    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super init];
        if (self) {
            unsigned int outCount;
            Ivar *ivarList = class_copyIvarList([Person class], &outCount);
            for (NSInteger i = 0; i < outCount; i++) {
                const char *cName = ivar_getName(ivarList[i]);
                NSString *name = [NSString stringWithUTF8String:cName];
                [self setValue:[aDecoder decodeObjectForKey:name] forKey:name];
            }
        }
        return self;
    }
    
    /*
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        NSString *selString = NSStringFromSelector(sel);
        if ([selString isEqualToString:@"walkOnTheStreet:"]) {
            // 为一个没有实现的方法动态添加实现
     
             cls:类
             name:没有实现的方法名
             IMP:要添加的实现
             types:动态添加的实现的类型编码
     
            class_addMethod(self, @selector(walkOnTheStreet:), (IMP)walkFunc, "V@:@");
        }
        return [super resolveInstanceMethod:sel];
    }
    */
    void walkFunc(id self, SEL sel, NSString *str){
        NSLog(@"Person -- %s, %@", __func__, str);
    }
    
    // 切换消息转换对象 方式一
    
    /*
    - (id)forwardingTargetForSelector:(SEL)aSelector
    {
        NSString *selString = NSStringFromSelector(aSelector);
        if ([selString isEqualToString:@"walkOnTheStreet:"]) {
            self.dog = [Dog new];
            return self.dog;
            
        }
        else {
            return [super forwardingTargetForSelector:aSelector];
        }
    }
    */
    
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        if ([Dog instancesRespondToSelector:anInvocation.selector]) {
            self.dog = [Dog new];
            [anInvocation invokeWithTarget:self.dog];
        }
    }
    
    // 给方法制定一个有效的签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    {
        NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
        if (!methodSignature) {
            methodSignature = [Dog instanceMethodSignatureForSelector:aSelector];
        }
        return methodSignature;
    }
    

    runtime在类目中的使用

    /* 
     void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)     //为某个类关联某个对象
     id objc_getAssociatedObject(id object, const void *key)
     //获取到某个类的某个关联对象
     void objc_removeAssociatedObjects(id object) //移除已经关联的对象
    */
    

    可以为某个类关联对象

    - (void)setName:(NSString *)name {
        // objc:要关联的对象 key:成员变量对应的key值,@selector(属性名)value:value
        objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)name {
        return objc_getAssociatedObject(self, @selector(name));
    }
    

    相关文章

      网友评论

          本文标题:Runtime初识

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