zoukankan      html  css  js  c++  java
  • 利用runTime,实现以模型为主的字典转模型(注意与KVC的区别)

      将字典转化为模型,面向模型开发,是在开发中最为常用的功能。利用KVC可以将字典转换为模型,但是前提有三个约束,一个是必须保证模型的属性个数大于等于字典个数,二是属性名称与字典的key必须相同,三是对于模型中的基本数据类型无法转换。

      其中第一条与第三条,是其最大的弊端。例如,如果从服务器获取的数据字典,并不想使用所有的键值对。但是在开发中还是必须得全部将对应属性列出,全部进行转换(除非你一个一个写,不使用KVC)。

      下面的代码就可以解决上述问题:实现以模型为主,将字典数据进行部分转化,并识别基本数据类型。约束仅仅是要求模型属性名称与字典KEY保持一致(因为底层还是使用KVC);

     1 //
     2 //  NSObject+Value.m
     3 //
     4 //  Created by shunzi 5-10-2014.
     5 //  Copyright (c) 2014年 shunzi. All rights reserved.
     6 //
     7 
     8 #import "NSObject+Value.h"
     9 #import <objc/message.h>
    10 #import <objc/runtime.h>
    11 
    12 @implementation NSObject (Value)
    13 - (void)setValues:(NSDictionary *)values
    14 {
    15     Class c = [self class];
    16     
    17     while (c) {
    18         // 1.获得所有的成员变量
    19         unsigned int outCount = 0;
    20         Ivar *ivars = class_copyIvarList(c, &outCount);
    21 
    22         for (int i = 0; i<outCount; i++) {
    23             Ivar ivar = ivars[i];
    24             
    25             // 2.属性名
    26             NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)];
    27             
    28             // 删除最前面的_
    29             [name replaceCharactersInRange:NSMakeRange(0, 1) withString:@""];
    30             
    31             // 3.取出属性值
    32             NSString *key = name;
    33             if ([key isEqualToString:@"desc"]) {
    34                 key = @"description";
    35             }
    36             if ([key isEqualToString:@"ID"]) {
    37                 key = @"id";
    38             }
    39             id value = values[key];
    40             if (!value) continue;
    41             
    42             // 4.SEL
    43             // 首字母
    44             NSString *cap = [name substringToIndex:1];
    45             // 变大写
    46             cap = cap.uppercaseString;
    47             // 将大写字母调换掉原首字母
    48             [name replaceCharactersInRange:NSMakeRange(0, 1) withString:cap];
    49             // 拼接set
    50             [name insertString:@"set" atIndex:0];
    51             // 拼接冒号:
    52             [name appendString:@":"];
    53             SEL selector = NSSelectorFromString(name);
    54             
    55             // 5.属性类型
    56             NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
    57             
    58             if ([type hasPrefix:@"@"]) { // 对象类型
    59                 objc_msgSend(self, selector, value);
    60             } else  { // 非对象类型
    61                 if ([type isEqualToString:@"d"]) {
    62                     objc_msgSend(self, selector, [value doubleValue]);
    63                 } else if ([type isEqualToString:@"f"]) {
    64                     objc_msgSend(self, selector, [value floatValue]);
    65                 } else if ([type isEqualToString:@"i"]) { 
    66                     objc_msgSend(self, selector, [value intValue]);
    67                 }  else { 
    68                     objc_msgSend(self, selector, [value longLongValue]);
    69                 }
    70             }
    71         }
    72         
    73         c = class_getSuperclass(c);
    74     }
    75 }
    76 @end

     头文件仅仅包含对此方法的声明,所以不在此粘贴

  • 相关阅读:
    javaweb开发之解决全站乱码
    redis加入开机启动服务
    linux下安装memcache
    关于本地连接虚拟机(centos)里的mongodb失败问题
    oracle存储过程中返回一个程序集
    面向对象进阶(二)----------类的内置方法
    面向对象进阶(一)
    面向对象的三大特性之----------封装
    面向对象的三大特性之----------多态
    面向对象的三大特性之----------继承
  • 原文地址:https://www.cnblogs.com/dashunzi/p/3741656.html
Copyright © 2011-2022 走看看