RunTime机制详解(一)

了解RunTime机制能都让我们在对OC底层实现的认识有一个质的飞越,RunTime的功能十分强大。

一、利用RunTime机制来获取所有的属性

#pragma mark --- 获取所有属性
/*
 一、objc_property_t:声明属性的类型,是一个指向objc_property结构体的指针,只能获取所有的属性,并不能获取成员变量
 typedef struct objc_property *objc_porperty_t;
 二、操作函数
 class_copyPropertyList      获取所有属性(并不会获取无@property声明的成员变量)
 property_getName            获取属性名
 property_copyAttributeList  获取所有属性特性
 property_getAttributes      获取属性特性描述字符串
 (返回的是objc_property_attribute_t结构体列表,objc_property_attribute_t结构体包含name和value,常用属性如下:
 属性类型   name值:T  value:变化
 编码类型   name值:C(copy) &(strong) W(weak) 空(assign)等  value:无
 非/原子性  name值:空(atomic)  N(nonatomic)             value:无
 变量名称   name值:V   value:变化
 )
 */
二、利用RunTime机制来获取成员变量。

#pragma mark --- 获取成员变量(成员变量)
/*
 一、 Ivar:实例变量类型,是一个指向objc_ivar结构体的指针,可以获取成员变量(包括私有成员变量)、属性
 typedef struct objc_ivar *Ivar;
 二、  操作函数
 class_copyIvarList          获取所有成员变量
 ivar_getName                获取成员变量名
 ivar_getTypeEncoding        获取成员变量类型编码
 class_getInstanceVarialbe   获取指定名称的成员变量
 object_getIvar              获取某个对象成员变量的值
 object_setIvar              设置某个对象成员变量的值
 */
+ (void)runtime_Ivars{
    unsigned int outCount = 0;
    Ivar * ivars = class_copyIvarList([Property_Model class], &outCount);
    for (unsigned int i = 0; i < outCount; i ++) {
        Ivar ivar = ivars[i];
        const char * name = ivar_getName(ivar);
        const char * type = ivar_getTypeEncoding(ivar);
        NSLog(@"类型为%s的%s",type,name);
    }
    free(ivars);
}
三、利用RunTime机制来获取私有变量

#pragma mark --- 访问私有变量
+ (void)runtime_private_Property{
    
/**
       我们知道,OC中没有真正意义上的私有变量和方法,要让成员变量私有,要放在m文件中声明,不对外暴露。如果我们知道这个成员变量的名称,可以通过runtime获取成员变量,再通过getIvar来获取它的值

 */
    
    Ivar ivar = class_getInstanceVariable([Property_Model class], "str_private");
    Property_Model * model = [[Property_Model alloc] init];
    [model modelPlay];
     NSLog(@"%@",object_getIvar(model, ivar));
    
}

四、利用RunTime机制来快速实现归档解档

-(id)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        unsigned int outCount;
        Ivar * ivars = class_copyIvarList([self class], &outCount);
        for (int i = 0; i < outCount; i ++) {
            Ivar ivar = ivars[i];
            NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            [self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
        }
    }
    return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int outCount;
    Ivar * ivars = class_copyIvarList([self class], &outCount);
    for (int i = 0; i < outCount; i ++) {
        Ivar ivar = ivars[i];
        NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
}

五、字典转模型的内部实现

我们都知道字典转模型的方法,但并不明白其中真正的方法实现,我们要的是知其然也要知其所以然。

-(instancetype)initWithDict:(NSDictionary *)dic{
    if (self = [self init]) {
        NSMutableArray * keys = [NSMutableArray array];
        NSMutableArray * attributes = [NSMutableArray array];
        unsigned int outCount;
        objc_property_t * properties = class_copyPropertyList([self class], &outCount);
        for (int i = 0 ; i < outCount; i ++) {
            objc_property_t property = properties[i];
            //通过property_getName函数获得属性的名字
            NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
            [keys addObject:propertyName];
            //通过property_getAttributes函数可以获得属性的名字和@encode编码
            NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
            [attributes addObject:propertyAttribute];
        }
        free(properties);//立即释放properties指向的内存
        for (NSString * key in keys) {
            if ([dic valueForKey:key] == nil) continue;
            [self setValue:[dic objectForKey:key] forKey:key];
        }
    }
    return self;
}

代码传送门https://github.com/fuzongjian/RuntimeStudy.git


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值