ios 应用实现快速的临时缓存之JSON 转化成模型


前缀:

    从本章开始,连续三章介绍如何实现iOS应用数据的快速缓存。

其中,第一章讲如何将JSON转化成模型对象,

第二章讲如何实现模型的自动化归档,

第三章讲快速缓存的实现。

  


第一章 ios JSON对象转化成模型

    iOS中官方介绍的应用架构模式是MVC模式,也就是model- view - controller

通常model 是指用户定义的一些属性数据,比如姓名,年龄,学校等等。这些数据

通常会从服务器获取,从服务器获取后,得到JSON对象。这里就介绍如何将一个

JSON对象转化成对应的模型。

   

比如定义一个学生的模型。


@interface:NSObject

@property(nonatomic.strong) NSString *name;

@property(nonatomic.strong) NSString *age;

@property(nonatomic.strong) NSString *grade;

@property(nonatomic.strong) NSString *className;


@end;


当前有一个Json对象如下


@{@"name":@"peter",

@"age":@"16",

@"grade":@"3",

@className:@"五年纪一班"

}


而把上述JSON对象转化成相关模型的方法

其实有两种。

1.  在上述模型的实现中,实现JSON转化成模型的方法

+(Student*)initWithDic:(NSDictionary*)dic
{
    Student *obj = [Student new];
    obj.name = dic[@"name"];
    obj.age = dic[@"age"];
    obj.grade = dic[@"grade"];
    obj.className = dic[@"className"];
    return obj;
}



上面这样写是没问题的。


如果有更高效的方法,作为NSObject的扩展,不用每一个模型都写字典-》模型多好。

事实上这是可以实现的。下面说说实现的两个核型方法。


1.

调用runtime 的

class_copyPropertyList()

函数获取模型类的属性列表  array;

2.

便利array中的属性名,并查找对应于NSDictionary中的数据

如果有数据,调用setValue:forKey:方法给该属性赋值,

如果没有数据,则不赋值。


归根到底不外乎上面1、2两个步骤。


下面将NSObject的扩展,也就是从字典转化成模型的代码贴出来。如下:

-(id)initFromDic:(NSDictionary *)dic
{
    if (self.class == NSObject.class) {
        return nil;
    }
    else {
        self = [self init];
    }
    
    if (self) {
        Class currentClass = self.class;
        NSMutableArray *propertyList = [[NSMutableArray alloc] init];
        NSMutableArray *attributeNameList = [[NSMutableArray alloc] init];
        
        while (currentClass && currentClass != NSObject.class)
        {
            unsigned int count = 0;
            objc_property_t *pList =  class_copyPropertyList(currentClass, &count);
            if (count > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    NSString *propertyString = [NSString stringWithUTF8String:property_getName(pList[i])];
                    [propertyList addObject:propertyString];
                    
                    NSString *attributeString = [NSString stringWithUTF8String:property_getAttributes(pList[i])];
                    [attributeNameList addObject:attributeString];
                }
            }
            free(pList);
            currentClass = class_getSuperclass(currentClass);
        }
        
        
        if (propertyList.count == 0) {
            return self;
        }
        
        
        for (int i=0; i<propertyList.count ; i++) {
            
            NSString *key = propertyList[i];
            NSString *propertyType = [self getClassNameFromPropertyName:attributeNameList[i]];
            
            id obj = [dic objectForKey:key];
            if (obj == nil) {
                continue;
            }
            
            if (propertyType == nil) {
                [self setValue:obj forKey:key];
            }
            else if (([propertyType isEqualToString:@"NSMutableArray"] || [propertyType isEqualToString:@"NSArray"])
                     && [obj isKindOfClass:[NSArray class]]) {
                
                    SEL classNameMethod = NSSelectorFromString(@"classNameForKeys");
                    if ([self respondsToSelector:classNameMethod]) {
                        
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                        
                        NSDictionary *classNameDic = (NSDictionary*)[self performSelector:classNameMethod];
                        Class propertyClass = [classNameDic objectForKey:key];
                        
                        if (propertyClass) {
                            NSMutableArray *objArray = [[NSMutableArray alloc] init];
                            for (NSDictionary *objDic in obj) {
                                id transferedObj = [propertyClass objectFromDic:objDic];
                                if (transferedObj) {
                                    [objArray addObject:transferedObj];
                                }
                            }
                            [self setValue:objArray forKey:key];
                        }
                        else {
                            [self setValue:obj forKey:key];
                        }
                    }
                    else {
                        [self setValue:obj forKey:key];
                    }
            }
            else {
                
                Class keyClass = NSClassFromString(propertyType);
                if (keyClass) {
                    id transferedObj = [keyClass objectFromDic:obj];
                    if (transferedObj) {
                        [self setValue:transferedObj forKey:key];
                    }
                }
            }
        }
    }
    return self;
}



-(NSString *)getClassNameFromPropertyName:(NSString*)name
{
    if (name == nil) {
        return nil;
    }
    
    NSString * className = nil;
    if ([[name substringWithRange:NSMakeRange(1, 1)] isEqualToString:@"@"]) {
        NSString *subRangeString = [name substringWithRange:NSMakeRange(3, 3)];
        if ([subRangeString isEqualToString:@"NSA"] || [subRangeString isEqualToString:@"NSM"]) {
            className = @"NSArray";
        }
        else {
            NSString *otherSystemString = [name substringWithRange: NSMakeRange(3, 2)];
            if ([otherSystemString isEqualToString:@"NS"]) {
                className = nil;
            }
            else {
                className = [[name componentsSeparatedByString:@"\""] objectAtIndex:1];
            }
        }
    }
    return className;
}


Demo 下载地址为:http://download.csdn.net/download/j_akill/9118955


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值