iOS - 持久化数据层搭建(Realm)

作者: 程序员咿呀咿呀哟 | 来源:发表于2016-05-31 19:46 被阅读341次

构思了好久,参考了很多人的代码,主要是参考同事的,尝试写了下数据层。
博文地址 http://linit.space/chi-jiu-hua-shu-ju-ceng-da-jian/
==github地址 pod文件还在制作中 https://github.com/Lin-IT-Lion/GQDataBase ==

设计思路

起初是想设计一个通用的构架,底层数据存储的实现方式可以任意替换,鉴于起太复杂,就先设计一个以Realm为数据核心的数据层,当然也可以设计的最终效果是这个核心可以任意替换,替换后上层用到数据存储的部分不需要变动。

一. 构架设计

数据持久化储蓄层.jpg
==适用的模式还是中规中矩的MVC。
上层业务使用的NormalModel可以不做变动,并且可以直接用NormalModel提供的方法进行数据操作。数据存储都由ModelDBContext操作NormalDBModel去实现。==
从图中可以看出,NormalModel与NormalDBModel可以用过一个ModelTransformer类进行互相的转化,数据的流向是将NormalModel转成NormalDBModel后存入数据库,反之亦然。用户使用的话,通过调用原本NormalModel的一些方法就可以实现数据存储。

二. 具体设计

==假设前提:用户使用MVC的方式==

从直接暴露给用户接触的接口说起。首先要使得用户原有的Model可以直接调用增删改查方法。那么就必须给原有的 Model 加上对应的方法,于是便需要提供一个 Category , 给 NSObject 类加上对应的方法定义如下

 @interface NSObject (GQDBOperation)

/**
 *  增加or修改
 */
- (BOOL)gq_DBaddOrUpdate;

/**
 *  删除
 */
- (BOOL)gq_DBdel;

/**
 *  查询
 *
 *  @param predicate 正则
 *
 *  @return 结果
 */
+ (NSArray *)gq_DBgetObjectsWithPredicate:(NSPredicate *)predicate;

/**
 *  查询全部
 *
 *  @return 结果
 */
+ (NSArray *)gq_DBgetAllObject;

/**
 *  删除全部
 *
 */
+ (BOOL)gq_DBdelAll;
@end

这样上层用户只需要直接调用对应的方法就可以了。

接下来要进行这些方法的具体实现,在之前的构架设计中已经提到,我们需要进行Model转化然后进行数据存储操作。但是要由原来的Model转化为我们的DBModel。定义DBModel的方式很多,反正我们先定一个BaseDBModel(继承自RLMObject),所有的DBModel都继承与他。(后来我想了下,dbmodel可能也可以不用自己定义,可以使用runtime的特性,动态生成对应类,不过这个暂时放在以后研究,本文还是用最简单的方法,自行定义) 普通的model定义DBModel的形式非常简单,只需要继承自BaseDBModel然后各个字段根据Realm的特性进行定义即可。如:

#import "GQSecNormalModel.h"
@interface GQNormalModel : NSObject

@property (nonatomic, copy) NSString *title;

@property (nonatomic, strong) NSNumber *nId;

@property (nonatomic, strong) GQSecNormalModel *oneModel;

@property (nonatomic, strong) NSMutableArray *oneModelList;

@end
@interface GQSecNormalModel : NSObject
@property (nonatomic, copy) NSString *smallTitle;
@property (nonatomic, copy) NSString *smallTitle1;
@end

@interface GQSecNormalDBModel : GQBaseDBModel

@property (nonatomic, copy) NSString *smallTitle;
@property (nonatomic, copy) NSString *smallTitle1;
@end

RLM_ARRAY_TYPE(GQSecNormalDBModel)

@interface GQNormalDBModel : GQBaseDBModel

@property (nonatomic, strong) NSNumber<RLMInt> *nId;

@property (nonatomic, copy) NSString *title;

@property (nonatomic, strong) GQSecNormalDBModel *oneModel;

@property (nonatomic, strong) RLMArray<GQSecNormalDBModel> *oneModelList;
@end

转换成DBModel之后,通过自定义的ModelDBContext进行数据库操作,当然,也可以直接通过DBModel操作数据库,之所以拆分开来只是为了代码逻辑更加清楚。

三. 具体实现

实现不在本文讨论范围内,直接传代码至github,大家自行参考。

四. 细节问题

  1. 为了使得框架与项目的耦合程度低一点,获取一些用户的信息,采用协议的方式。通过实现协议方法,返回给数据层一些必要的用户信息。
  2. 方便DBModel和普通Model的转化,采用Realm+json
  3. 主要通过协议的方式,提示用户去设置主键,与存储范围(用户相关or无关)

五. 性能分析

主要和Sqlite进行对比,调用Sqlite的方式采用第三方FMDB

02.jpg

从图中可以看出Realm明显在存储的过程中明显快于Sqlite,同样存储10000条数据,Sqlite需要6219ms,Realm仅仅需要1370ms,在读取操作的时候,Realm仅仅需要13ms而Sqlite需要94ms(图中的Realm 使用 1656ms并不是都在读取数据库而是做model转化,读取数据仅耗时13ms,实则存储过程中,真正存储的也只有300ms图中没有截图,其余1000ms也在model转化,而model转化是本框架做的与Realm无关)。
可见,使用Realm远好于Sqlite。

相关文章

网友评论

  • Dariel:赞一个,一直打算试试Realm

本文标题:iOS - 持久化数据层搭建(Realm)

本文链接:https://www.haomeiwen.com/subject/kkthdttx.html