http://blog.csdn.net/cooldragon/article/details/18991973

iOS开发中基于ORM的框架很多,如SQLitePersistentObject,实际开发中需求不同或场景不同,方式方法也就不同,有时项目中用不上ORM框架,或者出于公司或项目组习惯或规范、实际项目需求或技术要求等等原因,不会采用完整的ORM框架,但一些重复啰嗦的代码使用一定的ORM功能还是很能提高效率的。

基于性能或灵活性考虑,或复杂查询的需求,或项目组要求,项目中数据库存取一般直接用SQL或用FMDB的多些(某些产品研发型另说,软件架构设计是另一个话题,从笔者N年面试N多iOS开发者来看用FMDB的占了极大多数,不乏某某有名App),代码中使用字典、数组或自定义类(或叫实体)作为数据载体,FMDB的FMResultSet有个resultDictionary能够直接返回字典NSDictionary,再结合下面的辅助类,能够解决实体对象和字典(NSDictionary)的相互自动转换问题,不用一个Key一个Key,一个属性一个属性的自己去写代码了,避免重复手写烦杂和拼写错误的可能,大大的提高了开发效率。

  1. //
  2. //  EntityHelper.h
  3. //  使用前提条件是:字典的Key和实体对象属性的单词是一样的,大小可以忽略。
  4. //
  5. //  Created by LongJun on 13-1-28.
  6. //  Copyright (c) 2013年 RL. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @interface EntityHelper : NSObject
  10. //字典对象转为实体对象
  11. + (void) dictionaryToEntity:(NSDictionary *)dict entity:(NSObject*)entity;
  12. //实体对象转为字典对象
  13. + (NSDictionary *) entityToDictionary:(id)entity;
  14. @end
  1. //
  2. //  EntityHelper.m
  3. //  ARProjectForPad
  4. //
  5. //  Created by LongJun on 13-1-28.
  6. //  Copyright (c) 2013年 RL. All rights reserved.
  7. //
  8. #import "EntityHelper.h"
  9. #import <objc/runtime.h>
  10. @implementation EntityHelper
  11. #pragma mark - Custom Method
  12. + (void) dictionaryToEntity:(NSDictionary *)dict entity:(NSObject*)entity
  13. {
  14. if (dict && entity) {
  15. for (NSString *keyName in [dict allKeys]) {
  16. //构建出属性的set方法
  17. NSString *destMethodName = [NSString stringWithFormat:@"set%@:",[keyName capitalizedString]]; //capitalizedString返回每个单词首字母大写的字符串(每个单词的其余字母转换为小写)
  18. SEL destMethodSelector = NSSelectorFromString(destMethodName);
  19. if ([entity respondsToSelector:destMethodSelector]) {
  20. [entity performSelector:destMethodSelector withObject:[dict objectForKey:keyName]];
  21. }
  22. }//end for
  23. }//end if
  24. }
  25. + (NSDictionary *) entityToDictionary:(id)entity
  26. {
  27. Class clazz = [entity class];
  28. u_int count;
  29. objc_property_t* properties = class_copyPropertyList(clazz, &count);
  30. NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
  31. NSMutableArray* valueArray = [NSMutableArray arrayWithCapacity:count];
  32. for (int i = 0; i < count ; i++)
  33. {
  34. objc_property_t prop=properties[i];
  35. const char* propertyName = property_getName(prop);
  36. [propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
  37. //        const char* attributeName = property_getAttributes(prop);
  38. //        NSLog(@"%@",[NSString stringWithUTF8String:propertyName]);
  39. //        NSLog(@"%@",[NSString stringWithUTF8String:attributeName]);
  40. id value =  [entity performSelector:NSSelectorFromString([NSString stringWithUTF8String:propertyName])];
  41. if(value ==nil)
  42. [valueArray addObject:[NSNull null]];
  43. else {
  44. [valueArray addObject:value];
  45. }
  46. //        NSLog(@"%@",value);
  47. }
  48. free(properties);
  49. NSDictionary* returnDic = [NSDictionary dictionaryWithObjects:valueArray forKeys:propertyArray];
  50. NSLog(@"%@", returnDic);
  51. return returnDic;
  52. }
  53. @end

实际使用(逻辑层)示例:

  1. //业务需要返回实体对象
  2. - (UserSCOInfoEntity*)loadStudyRecord:(UserSCOInfoQuery*)query
  3. {
  4. UserSCOInfoEntity *userSCOInfo = nil;
  5. @try {
  6. //
  7. NSDictionary *resultDict = [self loadStudyRecordForDict:query];
  8. if (!resultDict) return nil;
  9. //字典值自动填充到实体对象属性
  10. [EntityHelper dictionaryToEntity:resultDict entity:userSCOInfo];
  11. }
  12. @catch (NSException *exception) {
  13. NSAssert1(0, @"Exception=%@", exception.reason);
  14. }
  15. @finally {
  16. }
  17. return userSCOInfo;
  18. }
  19. //业务需要直接返回字典
  20. - (NSDictionary*)loadStudyRecordForDict:(UserSCOInfoQuery*)query
  21. {
  22. if (!query || !query.userID || !query.courseID || !query.scoID || !query.type || !query.typeID) {
  23. NSAssert(0, @"UserSCOInfoQuery对象或属性不能为空");
  24. return nil;
  25. }
  26. NSDictionary *resultDict = nil;
  27. FMDatabase *db = [FMDatabase databaseWithPath:[Common sharedInstance].localMainDb];
  28. @try {
  29. if (![db open]) {
  30. [db release];
  31. //NSLog(@"db open fail");
  32. return nil;
  33. }
  34. FMResultSet *s = [db executeQuery:@"SELECT … "];
  35. while ([s next]) {
  36. resultDict = [s resultDictionary];
  37. break;
  38. }
  39. [s close];
  40. if (!resultDict) {
  41. //            NSString *errMsg = [db lastErrorMessage];
  42. //NSLog(@"[db lastErrorMessage]=%@",errMsg);
  43. }
  44. }
  45. @catch (NSException *exception) {
  46. NSAssert1(0, @"Exception=%@", exception.reason);
  47. }
  48. @finally {
  49. [db close];
  50. }
  51. return resultDict;
  52. }

当然,以上代码有一定应用场景,有一定的局限性,比如:
字典的Key和实体对象属性的单词必须是一样的(大小可以忽略),这里没有使用外部映射文件主要也是为了简化代码和项目的需要决定的。

Objective-C中ORM的运用:实体对象和字典的相互自动转换的更多相关文章

  1. Git.Framework 框架随手记--ORM查询返回实体对象

    使用ORM有一个优势,可以通过某种机制将数据库中的数据转化为自己想要的对象形式数据.本章记录一下如何使用Git.Framework返回实体对象 一. Git.Framework 中提供的方法 在Git ...

  2. hibernate 实体对象的三种状态以及转换关系。

    最新的Hibernate文档中为Hibernate对象定义了四种状态(原来是三种状态,面试的时候基本上问的也是三种状态),分别是:瞬时态(new, or transient).持久态(managed, ...

  3. EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充

    EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) EO理论上 ...

  4. 静态方法中不能new内部类的实体对象

    原因如下: 1.内部类可以访问外部类的成员变量 2.对象创建完成后对象的成员变量才会被分配空间 3.main的静态方法执行时可以不存在外部类,不创建实体对象 4.内部类能访问成员变量意味着一定存在外部 ...

  5. 项目中常用方法总结(将将DataTable数据集映射到实体对象)【转】

    本篇把项目中用到的一些通用方法总结出来, 这些方法因为经常需要在项目中用到,所以把它们归纳在一起, 形成一个.dll 文件是一个理想的选择. 这样也便于日后缩短开发周期. 一. 把一个DataGrid ...

  6. 在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be closed first”

    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be ...

  7. CAD由一个自定义实体事件中的id得到自定义实体对象(com接口VB语言)

    由一个自定义实体事件中的id得到自定义实体对象.该函数只能在自定义实体事件中调用. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 ...

  8. Hibernate中实体对象的状态

    实体对象的状态 这里的实体对象是指Hibernate的O/R映射关系中的域对象(即O/R中的O).实体对象的生命周期是指实体对象由产生到被GC回收的一段过程,实体对象的生命周期包括3种状态:自由状态( ...

  9. EBS OAF开发中实体对象和视图对象的属性设置器

    EBS OAF开发中实体对象和视图对象的属性设置器 (版权声明.本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 源文: Home > Oracle ...

随机推荐

  1. Vm-Ubuntu下配置Qt开发环境

    在昨天的Ubuntu换降下,安装Qt发现编译的时候是缺少opengl的 奈何找了好多方式都无法安装opengl 今天看到另一位大神写的,才发下自己找的还是有问题 大神帖子网址:http://blog. ...

  2. Struts2(二.用户登录模块)

    1.编写Javabean /src/myuser/User.java 在strut1中,Javabean需要继承于struts1 api中的ActionForm类.struts2没有此要求 strut ...

  3. Linux开发C语言规范

    -Iinclude:找头文件目录 ,获取头文件的目录 -C:创建.o文件 .h:文件用来声明函数,即写一个函数名. 如 int add(); int div(); int mul(); .c:文件定义 ...

  4. android4.1 Wifi 浅析

    简单分析下wifi相关类,首先了解几个主要概念 AsyncChannel 简单理解: AsyncChannel,就是借助Messenger 机制,让两个不同的handler之间进行通信. AsyncC ...

  5. Windows下LATEX排版论文攻略—CTeX、JabRef使用心得

    笔者刚刚接触到TEX排版,相关知识完全空白,用了两天时间学习并完成了一篇论文的完整排版. 期间遇到不少小问题,着实辛苦,分享至上,现将其解决办法总结归纳,共同学习. 一.工具介绍 TeX是一个很好排版 ...

  6. 【Python】python函数每日一讲 - dir()

    最近确实是有些忙,刚过了年,积攒了很多事情需要处理,所以每日一函数只能是每两天更新一篇,在这里和大家致歉. 今天我们来看一个非常重要的函数:dir() 中文说明:不带参数时,返回当前范围内的变量.方法 ...

  7. web相关基础知识2

    2017-12-14 17:14:22 块元素 典型代表,Div,h1-h6,p,ul,li 特点: ★独占一行 ★可以设置宽高  ★ 嵌套(包含)下,子块元素宽度(没有定义情况下)和父块元素宽度默认 ...

  8. 项目常用解决方案之SystemSetting.xml文件的修改与读取

    Winform及WPF项目中经常会用到类似SystemSetting.xml等类似的文件用于保存CLIENT的数据,比如登录过的用户名或密码以及其他设置.所以就想到一个解决方法,可以用到所有有此需求的 ...

  9. 算法(5)Jump Game

    题目:非负数的数组,每个数组元素代表这你能最大跨越多少步,初始在0的位置,问,能不能正好调到数组的最后一位! https://leetcode.com/problems/jump-game/#/des ...

  10. [Java] Java常见错误

    1.处理java错误"编码 GBK 的不可映射字符" (1)首先记事本打开java源文件 (2)然后另存为,选择ANSI编码 (3)覆盖 (4)再试一下,ok,编译通过.