Runtime学习笔记(一)——成员变量和属性

最近开始学习runtime,想挖掘iOS的运行机制,经过几天折腾,终于初窥门径,首先记录关于成员变量和属性的学习内容

1.获取成员变量

Ivar: 实例变量类型,是一个指向objc_ivar结构体的指针    

typedef struct objc_ivar *Ivar;


model的声明:

#import <Foundation/Foundation.h>

@interface Model : NSObject
{
    NSString * _string1;
}
@property NSString * string2;
@property (nonatomic, copy) NSDictionary * dict;


@end
关键代码:

#import "ViewController.h"
#import "Model.h"
#import <objc/runtime.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //获取成员变量
    [self test1];
}

-(void)test1{
    unsigned int outCount = 0;
    Ivar * ivars =class_copyIvarList([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 \n名称:%s ", type, name);
    }
    //释放内存
    free(ivars);
}

2.获取属性

objc_property_t:声明的属性的类型,是一个指向objc_property结构体的指针

typedef struct objc_property *objc_property_t;

关键代码:

-(void)test2{
    unsigned int outCount = 0;
    objc_property_t * properties = class_copyPropertyList([Model class], &outCount);
    for (unsigned int i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        //属性名
        const char * name = property_getName(property);
        //属性描述
        const char * propertyAttr = property_getAttributes(property);
        NSLog(@"属性描述为 %s 的 %s ", propertyAttr, name);
        
        //属性的特性
        unsigned int attrCount = 0;
        objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount);
        for (unsigned int j = 0; j < attrCount; j++) {
            objc_property_attribute_t attr = attrs[j];
            const char * name = attr.name;
            const char * value = attr.value;
            NSLog(@"属性的描述:%s 值:%s", name, value);
        }
        free(attrs);
        NSLog(@"\n===============\n");
    }
    free(properties);
    
}
其他代码同test1。


3.获取在.m中声明的变量

#import "JsonToModelBaseClass.h"

@interface JsonToModelBaseClass ()
{
    NSString * _string1;
}
@end
@implementation JsonToModelBaseClass
@end
关键代码:

-(void)test3{
    JsonToModelBaseClass * baseModel = [[JsonToModelBaseClass alloc] init];

    Ivar ivar = class_getInstanceVariable([baseModel class], "_string1");
    NSString * str = object_getIvar(baseModel, ivar);
    NSLog(@"%@", str);
}

4.json转model

首先创建一个NSObject+RunTime的分类

#import <Foundation/Foundation.h>

@interface NSObject (RunTime)

-(instancetype)initWithDict:(NSDictionary *)dict;

@end
关键代码
#import "NSObject+RunTime.h"
#import <objc/runtime.h>



@implementation NSObject (RunTime)
-(instancetype)initWithDict:(NSDictionary *)dict {
    if (self == [self init]) {
        
        [self setPropertyWithDict:dict];
    }
    return self;
}

-(void)setPropertyWithDict:(NSDictionary *)dict{
    //(1)获取类的属性及属性对应的类型
    NSMutableArray * keyArray = [NSMutableArray array];
    NSMutableArray * attributeArray = [NSMutableArray array];

    unsigned int outCount = 0;
    objc_property_t * properties = class_copyPropertyList([self class], &outCount);
    for (unsigned int i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        //通过property_getName函数获得属性的名字
        NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        [keyArray addObject:propertyName];
        //通过property_getAttributes函数可以获得属性的名字和@encode编码
        NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
        [attributeArray addObject:propertyAttribute];
    }
    //释放properties
    free(properties);
    
    //(2)根据类型给属性赋值
    for (NSString * key in keyArray) {
        if ([dict valueForKey:key] == nil) {
            continue;
        }
        [self setValue:[dict valueForKey:key] forKey:key];
    }
}
然后创建model声明属性

#import <Foundation/Foundation.h>

@interface JsonToModelBaseClass : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, copy) NSString * age;
@property (nonatomic, copy) NSString * intro;
@end
实现

-(void)test4{
    NSDictionary * dict = @{@"name" : @"xiaoming",
                            @"age" : @"20",
                            @"intro" : @"SB"};
    JsonToModelBaseClass * baseModel = [[JsonToModelBaseClass alloc] initWithDict:dict];
    NSLog(@"%@", baseModel);
    
}
这样就会像KVC一样,直接把json中相应的数据赋值给model.







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值