用字典给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:] uppercaseString];
NSString *setterSelStr = \
[NSString stringWithFormat:@"set%@%@:", capital, [attributeName substringFromIndex:]];
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 = ;
objc_property_t *properties = class_copyPropertyList(class, &propertyCount); for (unsigned int i = ; 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" : @,
@"addressInfo" : @{@"HuBei": @"WeiHan"},
@"events" : @[@"One", @"Two", @"Three"],
@"id" : @""}; // 打印出属性值
NSLog(@"%@", model.dataDictionary); return YES;
} @end

以下就是使用流程了:

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

  1. 用字典给Model赋值

    用字典给Model赋值 此篇教程讲述通过runtime扩展NSObject,可以直接用字典给Model赋值,这是相当有用的技术呢. 源码: NSObject+Properties.h 与 NSObje ...

  2. 【转】kubernetes 中 deployment 支持哪些键值

    这个比较全,可以参考 ================= https://www.addops.cn/post/kubernetes-deployment-fileds.html ========== ...

  3. java 把json对象中转成map键值对

    相关:Json对象与Json字符串的转化.JSON字符串与Java对象的转换 本文的目的是把json串转成map键值对存储,而且只存储叶节点的数据 比如json数据如下: {responseHeade ...

  4. 如何将Map键值的下划线转为驼峰

    本文不再更新,可能存在内容过时的情况,实时更新请移步我的新博客:如何将Map键值的下划线转为驼峰: 例,将HashMap实例extMap键值下划线转为驼峰: 代码: HashMap<String ...

  5. Java Map 键值对排序 按key排序和按Value排序

    一.理论准备 Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. TreeMap:基于红黑树(Red-Black tre ...

  6. 枚举类返回Map键值对,绑定到下拉框

    有时候,页面的下拉框要显示键值对,但是不想从数据库取,此时我们可以写一个枚举类, Java后台代码 1.枚举类 import java.util.HashMap; import java.util.M ...

  7. 根据map键值对,生成update与select语句,单条执行语句

    方法 constructUpdateSQL private static String constructUpdateSQL(String tableName, List<Map<Stri ...

  8. vue中如果在页面中v-model的是字典,那么在定义字典的时候,需要明确定义键值为''或者[],否则给字典的键值赋值后页面不显示

    如题 在template模板中 {{}} {{form_temp.blOwnerMemberList}} #是字典的形式哦 {{}} 在return的属性中 form_temp: { blOwnerM ...

  9. list转map 键值对

    Map<Long,Account> map = new HashMap<Long,Account>(); for(int i=0;i<list.size();i++){ ...

随机推荐

  1. B+树 -- Java实现

    一.B+树定义 B+树定义:关键字个数比孩子结点个数小1的树. 除此之外B+树还有以下的要求: B+树包含2种类型的结点:内部结点(也称索引结点)和叶子结点.根结点本身即可以是内部结点,也可以是叶子结 ...

  2. springcloud-07-eureka HA的高可用配置

    单机版的eureka, 运行时间稍长, 就会在管理界面出现红色的警告, 为了消除这个警告, 可以使用eureka的高可用配置: 只需要写一个工程配置不同的配置文件, 然后启动多实例即可: 请参照单机版 ...

  3. Linux时间命令

    Linux一般有系统时间和硬件时间之分,date命令是显示和操作系统时间:hwclock用来操作硬件时间(日期).日期和时间很重要,比如错误的日期和时间会导致你不能编译程序. 1 date 用法:   ...

  4. haproxy 学习记录

    1.简易安装 make TARGET=linux26 prefix=/usr/local/haproxy install 启动haproxy在sbin目录,其余的在doc目录 2. 配置 hdr_be ...

  5. H5开发过程中修复的bug记录

    从2016年8月1日开始真正意义上的修复bug,也是自己开发之路的开端,希望在这里记录自己修bug过程中遇到的问题及解决方法,待能够自己开发需求的时候,计划记录开发新需求过程中遇到的问题,并且记录自己 ...

  6. Ubuntu18---VMware虚拟机中Ubuntu18.04系统,开机输入密码后无响应黑屏

    系统崩坏了,重装过几次,这次决定不充装了. 搜索大神解决方案后,了解到是图形界面程序损坏,可能是在更新内核或者安装软件的时候,把与xorg相关的文件给清除了. 解决方案如下: 1.登录系统进入,黑屏后 ...

  7. Linux多线程 - 基本操作

    0. 线程 vs 进程 何为线程?线程即轻量级进程,如何理解轻量级这个概念? 我们知道,Linux的资源分为用户空间资源和内核空间资源: 用户空间资源:用来存放用户自定义的一些数据,用户可直接控制: ...

  8. Visual Basic了解

    Visual Basic是一种由微软公司开发的结构化的.模块化的.面向对象的.包含协助开发环境的事件驱动为机制的可视化程序设计语言.这是一种可用于微软自家产品开发的语言.它源自于Basic编程语言.V ...

  9. c#基础学习(0630)之面向对象总习

    面向对象总习 1.封装.继承.多态 ****字段:存储数据,访问修饰符应该设置为private私有的 ****属性:保护字段,对字段的取值和赋值的限定 ****new关键字: 1.在堆中开辟空间(引用 ...

  10. Python__random库基本介绍

    random库是使用随机数的Python标准库 从概率论角度来说,随机数是随机产生的数据(比如抛硬币),但时计算机是不可能产生随机值,真正的随机数也是在特定条件下产生的确定值,只不过这些条件我们没有理 ...