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. 2015年开源前端框架盘点TOP20

    2015年,榜单根据github上star数作为排名依据.(榜单中大部分为组件式框架, react.Angular等基础框架不在此篇讨论) 1.Bootstrap 类别/语言:HTML.CSS.Jav ...

  2. 跳出for循环break和continue的区别

    1.break 跳出for循环,结束for循环 如果有两层循环,break只能跳出一层循环 2.continue 跳出本次循环,继续下一条数据的循环

  3. LeetCode - 67. Add Binary(4ms)

    Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...

  4. python基础训练营04-函数

    任务四  函数的关键字 函数的定义 函数参数与作用域 函数返回值 一.函数的关键字: def 二.函数的定义: 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号 ...

  5. BZOJ 3597 SCOI2014 方伯伯送椰子 网络流分析+SPFA

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3597 Description 四川的方伯伯为了致富,决定引进海南的椰子树.方伯伯的椰子园十 ...

  6. u盘中毒后文件夹没显示了

    今日,我的U盘插了有毒的电脑,直接中毒了,先是显示有木马,后是自行产生一些文件,接着文件夹没了,后来自己终于解决了,分享一下,自己先用工具将有嫌疑的文件提炼出来,经自行检查后处理,接着打开文件夹选项, ...

  7. python进制转换(二进制、十进制和十六进制)及注意事项

    使用内置函数实现进制转换实现比较简单,主要用到以下函数: bin().oct().int().hex() 下面分别详解一下各个函数的使用(附实例) 第一部分:其他进制转十进制 1.二进制转十进制 使用 ...

  8. Activiti工作流(三)——流程变量

    流程变量可以是流程中一系列参数,比如办理人(Assignee),消息(message)等.这些流程变量使得activiti能够应用于更为复杂的业务中,使得流程变得更加灵活可控. 场景(一) 图一:没有 ...

  9. 关于C标准

    关于C标准 1. 前言 本文从英文 C-FAQ (2004 年 7 月 3 日修订版) 翻译而来.本文的 中文版权为朱群英和孙云所有. 本文的内容可以自由用于个人目的,但 是不可以未经许可出版发行. ...

  10. Bootstrap中的Affix插件

    我们为什么要用bootstrap?因为懒!哦....不,是因为方便,呃...意思差不多. 今天来说说Affix这个插件,它可以使导航栏固定,免去了自己手写的麻烦,用着非常方便,废话不多说,下面是用法. ...