用字典给Model赋值并支持map键值替换

这个是昨天教程的升级版本,支持键值的map替换。

源码如下:

NSObject+Properties.h 与 NSObject+Properties.m

//
//  NSObject+Properties.h
//
//  Created by YouXianMing on 14-9-4.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (Properties)

@property (nonatomic, strong) NSDictionary *mapDictionary;

- (void)setDataDictionary:(NSDictionary*)dataDictionary;
- (NSDictionary *)dataDictionary;

@end
//
//  NSObject+Properties.m
//
//  Created by YouXianMing on 14-9-4.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "NSObject+Properties.h"
#import <objc/runtime.h>

@implementation NSObject (Properties)

#pragma runtime - 动态添加了一个属性,map属性
static char mapDictionaryFlag;
- (void)setMapDictionary:(NSDictionary *)mapDictionary
{
    objc_setAssociatedObject(self, &mapDictionaryFlag, mapDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSDictionary *)mapDictionary
{
    return objc_getAssociatedObject(self, &mapDictionaryFlag);
}

#pragma public - 公开方法

- (void)setDataDictionary:(NSDictionary*)dataDictionary
{
    [self setAttributes:[self mapDictionary:self.mapDictionary dataDictionary:dataDictionary]
                    obj:self];
}

- (NSDictionary *)dataDictionary
{
    // 获取属性列表
    NSArray *properties = [self propertyNames:[self class]];

    // 根据属性列表获取属性值
    return [self propertiesAndValuesDictionary:self properties:properties];
}

#pragma private - 私有方法

// 通过属性名字拼凑setter方法
- (SEL)getSetterSelWithAttibuteName:(NSString*)attributeName
{
    NSString *capital = [[attributeName substringToIndex:1] uppercaseString];
    NSString *setterSelStr =     [NSString stringWithFormat:@"set%@%@:", capital, [attributeName substringFromIndex:1]];
    return NSSelectorFromString(setterSelStr);
}

// 通过字典设置属性值
- (void)setAttributes:(NSDictionary*)dataDic obj:(id)obj
{
    // 获取所有的key值
    NSEnumerator *keyEnum = [dataDic keyEnumerator];

    // 字典的key值(与Model的属性值一一对应)
    id attributeName = nil;
    while ((attributeName = [keyEnum nextObject]))
    {
        // 获取拼凑的setter方法
        SEL sel = [obj getSetterSelWithAttibuteName:attributeName];

        // 验证setter方法是否能回应
        if ([obj respondsToSelector:sel])
        {
            id value      = nil;
            id tmpValue   = dataDic[attributeName];

            if([tmpValue isKindOfClass:[NSNull class]])
            {
                // 如果是NSNull类型,则value值为空
                value = nil;
            }
            else
            {
                value = tmpValue;
            }

            // 执行setter方法
            [obj performSelectorOnMainThread:sel
                                  withObject:value
                               waitUntilDone:[NSThread isMainThread]];
        }
    }
}

// 获取一个类的属性名字列表
- (NSArray*)propertyNames:(Class)class
{
    NSMutableArray  *propertyNames = [[NSMutableArray alloc] init];
    unsigned int     propertyCount = 0;
    objc_property_t *properties    = class_copyPropertyList(class, &propertyCount);

    for (unsigned int i = 0; i < propertyCount; ++i)
    {
        objc_property_t  property = properties[i];
        const char      *name     = property_getName(property);

        [propertyNames addObject:[NSString stringWithUTF8String:name]];
    }

    free(properties);

    return propertyNames;
}

// 根据属性数组获取该属性的值
- (NSDictionary*)propertiesAndValuesDictionary:(id)obj properties:(NSArray *)properties
{
    NSMutableDictionary *propertiesValuesDic = [NSMutableDictionary dictionary];

    for (NSString *property in properties)
    {
        SEL getSel = NSSelectorFromString(property);

        if ([obj respondsToSelector:getSel])
        {
            NSMethodSignature  *signature  = nil;
            signature                      = [obj methodSignatureForSelector:getSel];
            NSInvocation       *invocation = [NSInvocation invocationWithMethodSignature:signature];
            [invocation setTarget:obj];
            [invocation setSelector:getSel];
            NSObject * __unsafe_unretained valueObj = nil;
            [invocation invoke];
            [invocation getReturnValue:&valueObj];

            //assign to @"" string
            if (valueObj == nil)
            {
                valueObj = @"";
            }

            propertiesValuesDic[property] = valueObj;
        }
    }

    return propertiesValuesDic;
}

// 根据map值替换掉键值
- (NSDictionary *)mapDictionary:(NSDictionary *)map dataDictionary:(NSDictionary *)data
{
    if (map && data)
    {
        // 拷贝字典
        NSMutableDictionary *newDataDic = [NSMutableDictionary dictionaryWithDictionary:data];

        // 获取所有map键值
        NSArray *allKeys                = [map allKeys];

        for (NSString *oldKey in allKeys)
        {
            // 获取到value
            id value = [newDataDic objectForKey:oldKey];

            // 如果有这个value
            if (value)
            {
                NSString *newKey = [map objectForKey:oldKey];
                [newDataDic removeObjectForKey:oldKey];
                [newDataDic setObject:value forKey:newKey];
            }
        }

        return newDataDic;
    }
    else
    {
        return data;
    }
}

@end

注意:

这里给NSObject的category新添加了一个属性,叫mapDictionary

然后给member添加一个属性叫做memberID

以下是使用的情况:

//
//  AppDelegate.m
//  Runtime
//
//  Created by YouXianMing on 14-9-5.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "AppDelegate.h"
#import "NSObject+Properties.h"
#import "Model.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // 初始化model
    Model *model = [Model new];

    // 设置map值
    model.mapDictionary = @{@"id": @"memberID"};

    // 通过字典赋值
    model.dataDictionary = @{@"name"        : @"YouXianMing",
                             @"age"         : @26,
                             @"addressInfo" : @{@"HuBei": @"WeiHan"},
                             @"events"      : @[@"One", @"Two", @"Three"],
                             @"id"          : @"7788"};

    // 打印出属性值
    NSLog(@"%@", model.dataDictionary);

    return YES;
}

@end

以下就是使用流程了:

时间: 2024-10-16 19:13:28

用字典给Model赋值并支持map键值替换的相关文章

用字典给Model赋值

此篇教程讲述通过runtime扩展NSObject,可以直接用字典给Model赋值,这是相当有用的技术呢. 源码: NSObject+Properties.h 与 NSObject+Properties.m // // NSObject+Properties.h // // Created by YouXianMing on 14-9-4. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <Foundatio

Map 键值对

Map 键值对 * a:添加功能 V put(K key,V value):添加元素. * 如果键是第一次存储,就直接存储元素,返回null * 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值 * b:删除功能 * void clear():移除所有的键值对元素 * V remove(Object key):根据键删除键值对元素,并把值返回 * c:判断功能 * boolean containsKey(Object key):判断集合是否包含指定的键 * boolean contai

(一)Python入门-3序列:17字典-核心底层原理-内存分析-存储键值对过程

字典核心底层原理(重要) 字典对象的核心是散列表.散列表是一个稀疏数组(总是有空白元素的数组),数组的 每个单元叫做 bucket.每个 bucket 有两部分:一个是键对象的引用,一个是值对象的引 用. 由于,所有bucket 结构和大小一致,我们可以通过偏移量来读取指定 bucket. 一:将一个键值对放进字典的底层过程 >>> a = {} >>> a["name"]="jack" 假设字典 a对象创建完后,数组长度为 8:

用字典给Model(继承与NSObject的对象)赋值---------【iOS 开发】

此篇教程讲述通过runtime扩展NSObject,可以直接用字典给Model赋值,这是相当有用的技术呢. PS:关于runtime的详情以后会详细介绍 源码: NSObject+Property.h 与 NSObject+Property.m // // NSObject+Property.h // ModelValueTest1.0 // // Created by Lisa on 14-9-15. // Copyright (c) 2014年 Lisa. All rights reserv

【Go入门教程2】内置基础类型(Boolean、数值、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值

这小节我们将要介绍如何定义变量.常量.Go内置类型以及Go程序设计中的一些技巧. 定义变量 Go语言里面定义变量有多种方式. 使用var关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量类型放在变量名后面: // 定义一个名称为“variableName”,类型为"type"的变量 var variableName type 定义多个变量 // 定义三个类型都是“type”的变量 var vname1, vname2, vname3 type 定义变量并初始化值 // 初始化

[转]字典的快速赋值 setValuesForKeysWithDictionary

前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中 @property (nonatomic,copy)NSString *name; @property (nonatomic,copy)NSString *sex; @property (nonatomic,copy)NSString *age; 字典: NSDictionary *dic = @{@"name":@"张三",@"sex":@"男"

【iOS开发】字典的快速赋值 setValuesForKeysWithDictionary

前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中 @property (nonatomic,copy)NSString *name; @property (nonatomic,copy)NSString *sex; @property (nonatomic,copy)NSString *age; 字典: NSDictionary *dic = @{@"name":@"张三",@"sex":@"男"

字典的快速赋值 setValuesForKeysWithDictionary

字典的快速赋值 setValuesForKeysWithDictionary ? 前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中    @property (nonatomic,copy)NSString *name;    @property (nonatomic,copy)NSString *sex;    @property (nonatomic,copy)NSString *age; 字典:     NSDictionary *dic = @{@"nam

各种Map的区别,想在Map放入自定义顺序的键值对

今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序. 一.简单介绍Map 在讲解Map排序之前,我们先来稍微了解下map.map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等.其中这四者的区别如下(简单介绍): HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接