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. 树莓派的WIFI配置

    参考网址: http://www.cnblogs.com/iusmile/archive/2013/03/30/2991139.html http://my.oschina.net/pikeman/b ...

  2. 学习人工智能的第五个月[字典学习[Dictionary Learning,DL]]

    摘要: 大白话解释字典学习,分享第五个月的学习过程,人生感悟,最后是自问自答. 目录: 1.字典学习(Dictionary Learning,DL) 2.学习过程 3.自问自答 内容: 1.字典学习( ...

  3. 在ubuntu下 使用Jetty 和 Maven 开发 HelloWorld

    1 安装JDK 我以前安装过,这里就不说了. 2 安装maven 去官网下载 解压 添加环境变量   gedit ~/.bashrc export JETTY_HOME=/home/roc/libs/ ...

  4. MongoDB Linux下的安装和启动

    1. 下载MongoDB,此处下载的版本是:mongodb-linux-i686-1.8.1.tgz.tar. http://fastdl.mongodb.org/linux/mongodb-linu ...

  5. html5实现web app摇一摇换歌

    微信可以摇歌曲,根据声音识别出歌曲,然后返回歌曲信息,利用html5的deviceOrientation特性和deviceMotion事件也可以在web app上实现类似于微信摇一摇的功能,原生的ap ...

  6. Mybatis学习系列(五)关联查询

    前面几节的示例基本都是一些单表查询,实际项目中,经常用到关联表的查询,比如一对一,一对多等情况.在Java实体对象中,一对一和一对多可是使用包装对象解决,属性使用List或者Set来实现,在mybat ...

  7. AndroidStudio3.0 注解报错Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor.

    体验最新版AndroidStudio3.0 Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ...

  8. [剑指Offer] 6.旋转数组的最小数字(二分法)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转 ...

  9. fckeditor的简单使用

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEnco ...

  10. hdu 1286 找新朋友 (欧拉函数)

    找新朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...