iOS开发之遍历Model类的属性并完善使用Runtime给Model类赋值

  在上篇博客iOS开发之使用Runtime给Model类赋值》中介绍了如何使用运行时在实体类的基类中添加给实体类的属性赋值的方法,这个方法的前提是字典的Key必须和实体类的Property Name相同,而后经过运行时来生成和执行Setter方法给Model类的属性赋值。html

  经过Runtime来给Model类属性赋值的好处是多多的,它便于代码的后期维护,而且提升了开发效率。当你拿到解析后的字典时你不用一个一个的经过key去把字典的值赋值给相应的Model类的属性,本篇博客中会给出如何去遍历Model中属性的值,而且给出字典的Key和Model的属性名不同的状况咱们该如何负值。数组

  接下来会在上一个博客代码基础上在Model基类中添加经过Runtime来遍历Model类的属性值。app

  1、获取Model的实体属性函数

  1.要想遍历Model类的属性,首先得经过Runtime来获取该Model类有哪些属性,输出Model的全部属性的值可不像遍历Dictionary和Array那样一个for循环搞定的,下面的方法是经过Runtime来获取Model类的属性字符串,并以数组的形式返回。代码以下:post

 1 ///经过运行时获取当前对象的全部属性的名称,以数组的形式返回
 2 - (NSArray *) allPropertyNames{
 3     ///存储全部的属性名称
 4     NSMutableArray *allNames = [[NSMutableArray alloc] init];
 5     
 6     ///存储属性的个数
 7     unsigned int propertyCount = 0;
 8     
 9     ///经过运行时获取当前类的属性
10     objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount);
11     
12     //把属性放到数组中
13     for (int i = 0; i < propertyCount; i ++) {
14         ///取出第一个属性
15         objc_property_t property = propertys[i];
16         
17         const char * propertyName = property_getName(property);
18         
19         [allNames addObject:[NSString stringWithUTF8String:propertyName]];
20     }
21     
22     ///释放
23     free(propertys);
24     
25     return allNames;
26 }

 

  2.获取到Model类的属性方法后须要把属性字符串生成get方法,咱们能够执行get方法来获取Model属性的值,下方的方法是根据属性字符串来获取属性的getter方法,OC中属性的getter方法的名字和属性的名字是一致的,生成getter方法比较简单,具体代码以下:测试

1 #pragma mark -- 经过字符串来建立该字符串的Setter方法,并返回
2 - (SEL) creatGetterWithPropertyName: (NSString *) propertyName{
3     
4     //1.返回get方法: oc中的get方法就是属性的自己
5     return NSSelectorFromString(propertyName);
6 }

 

  2、Get方法的执行atom

    接下来要作的是经过Runtime来执行Getter方法,这一块须要经过方法的签名来执行Getter方法。在OC的运行时中要执行的方法须要传入参数或者须要接收返回值时,须要经过方法的签名来调用方法。下面的代码就是建立方法的签名,而后经过签名来获取调用的对象,在下边的方中回调用上述两个方法在经过方法的签名来获取Model属性的值,具体代码以下:url

 1 - (void) displayCurrentModleProperty{
 2     
 3     //获取实体类的属性名
 4     NSArray *array = [self allPropertyNames];
 5  
 6     //拼接参数
 7     NSMutableString *resultString = [[NSMutableString alloc] init];
 8     
 9     for (int i = 0; i < array.count; i ++) {
10         
11         //获取get方法
12         SEL getSel = [self creatGetterWithPropertyName:array[i]];
13         
14         if ([self respondsToSelector:getSel]) {
15             
16             //得到类和方法的签名
17             NSMethodSignature *signature = [self methodSignatureForSelector:getSel];
18 
19             //从签名得到调用对象
20             NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
21 
22             //设置target
23             [invocation setTarget:self];
24             
25             //设置selector
26             [invocation setSelector:getSel];
27 
28             //接收返回的值
29             NSObject *__unsafe_unretained returnValue = nil;
30 
31             //调用
32             [invocation invoke];
33 
34             //接收返回值
35             [invocation getReturnValue:&returnValue];
36 
37             [resultString appendFormat:@"%@\n", returnValue];
38         }
39     }
40     NSLog(@"%@", resultString);
41     
42 }

 

  执行上述方法就能够输入Model中的属性的值,下面就在main函数中对Model赋完值后调用上述方法输出一下Model的属性值,调用代码以下所示:spa

1         BeautifulGirlModel *beautifulGirl = [BeautifulGirlModel modelWithDictionary:data];
2         
3         [beautifulGirl displayCurrentModleProperty];

  

  运行结果以下,下面的输出结果是Model中属性的值。code

 

  3、Dictionary的Key与Model的属性不一样的处理方式

    有时候会遇到字典的key和Model的属性不同的状况,那么如何去解决这个问题呢?最简单的作法是在具体的实体类中去维护一个映射关系方法,经过这个方法咱们能够获取相应的的映射关系。

    1.在Model的基类中添加一个返回映射字典的一个方法,而后在子类中进行重写,这个映射方法在基类中返回nil, 若是子类须要重写的话就对这个方法进行重写并返回映射字典。方法以下:

1 #pragma 返回属性和字典key的映射关系
2 -(NSDictionary *) propertyMapDic{
3     return nil;
4 }

 

  2.修改一下咱们的便利初始化方法,在有映射字典的状况和没有映射字典的状况下调用的方法是不同的,便利初始化方法的代码以下:

 1 - (instancetype)initWithDictionary: (NSDictionary *) data{
 2     {
 3         self = [super init];
 4         if (self) {
 5             if ([self propertyMapDic] == nil) {
 6                 [self assginToPropertyWithDictionary:data];
 7             } else {
 8                 [self assginToPropertyWithNoMapDictionary:data];
 9             }
10         }
11         return self;
12     }
13 }

 

  3.接下来就将实现有映射关系要调用的方法,这个方法就是经过映射关系把字典的key转换成与property的名字同样的字典,而后调用以前的赋值方法,具体代码以下:

 1 #pragma 根据映射关系来给Model的属性赋值
 2 -(void) assginToPropertyWithNoMapDictionary: (NSDictionary *) data{
 3     ///获取字典和Model属性的映射关系
 4     NSDictionary *propertyMapDic = [self propertyMapDic];
 5     
 6     ///转化成key和property同样的字典,而后调用assginToPropertyWithDictionary方法
 7     
 8     NSArray *dicKey = [data allKeys];
 9 
10     
11     NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:dicKey.count];
12     
13     for (int i = 0; i < dicKey.count; i ++) {
14         NSString *key = dicKey[i];
15         [tempDic setObject:data[key] forKey:propertyMapDic[key]];
16     }
17     
18     [self assginToPropertyWithDictionary:tempDic];
19     
20 }

 

  4.建立一个BadBoyModel, 并重写propertyMapDic方法,而且在propertyMapDic方法中给出映射关系并返回该映射关系对应的字典。

    (1)BadBoyModel的属性以下:

 1 //
 2 //  BadBoyModel.h
 3 //  BaseModelProject
 4 //
 5 //  Created by Mr.LuDashi on 15/7/24.
 6 //  Copyright (c) 2015年 ludashi. All rights reserved.
 7 //
 8 
 9 #import "BaseModelObject.h"
10 
11 @interface BadBoyModel : BaseModelObject
12 
13 @property (nonatomic, copy) NSString *boy1;
14 @property (nonatomic, copy) NSString *boy2;
15 @property (nonatomic, copy) NSString *boy3;
16 @property (nonatomic, copy) NSString *boy4;
17 
18 @end

 

    (2)重写映射方法,映射字典的key是要转换字典的key, Value是对应Model的属性名。

 1 //
 2 //  BadBoyModel.m
 3 //  BaseModelProject
 4 //
 5 //  Created by Mr.LuDashi on 15/7/24.
 6 //  Copyright (c) 2015年 ludashi. All rights reserved.
 7 //
 8 
 9 #import "BadBoyModel.h"
10 
11 @implementation BadBoyModel
12 
13 #pragma 返回属性和字典key的映射关系
14 -(NSDictionary *) propertyMapDic{
15     return @{@"keyBoy1":@"boy1",
16              @"keyBoy2":@"boy2",
17              @"keyBoy3":@"boy3",
18              @"keyBoy4":@"boy4",};
19 }
20 
21 @end

 

    5.在main函数中进行测试

      (1)、生成咱们的数值字典,字典的key与要赋值Model的属性不一样,下面的循环就是要生成测试使用的数据:

 1        //生成Dic的Key与Model的属性不同的字典。
 2         
 3         NSMutableDictionary *data1 = [[NSMutableDictionary alloc] init];
 4         
 5         //建立测试适用的字典
 6         for(int i = 1; i <= 4; i ++){
 7             NSString *key = [NSString stringWithFormat:@"keyBoy%d", i];
 8             
 9             NSString *value = [NSString stringWithFormat:@"我是第%d个坏男孩", i];
10             
11             [data1 setObject:value forKey:key];
12         }

 

      (2) 实例化Model并输出结果,固然以前的代码也是可使用的。

1         BadBoyModel *badBoyModel = [BadBoyModel modelWithDictionary:data1];
2         
3         [badBoyModel displayCurrentModleProperty];

 

    运行输出结果以下:

  

 

    今天博客就到这,至此,Model的基类最基本的方法封装的也就差很少了,根据具体需求能够在添加新的方法

相关文章
相关标签/搜索