概述
上一篇讲述了FMDB的最基本用法,用到的例子是缓存一张学生表,表里面都是些简单的字段。然而我们在实际项目开发中,大都使用FMDB缓存数据列表,比如网易新闻的新闻列表,QQ动态列表等。遵循MVC设计模式,我们请求下来的数据一般会建成数据模型,本编要讲的就是如何用FMDB缓存数据模型。下面就以新浪微博为例,看看如何使用FMDB缓存微博列表数据:
1、创建一个缓存微博数据的工具类DataBaseTool,点h文件如下
1 /**
2 * 缓存数据模型
3 *
4 * @param status 一条微博模型
5 */
6
7 +(void)addModel:(CZStatus*)status;
8
9 /**
10 * 缓存数据模型
11 *
12 * @param array 微博模型数组
13 */
14 +(void)addModelWithArray:(NSArray*)array;
15
16 /**
17 * 查询数据库
18 *
19 * @param param 参数模型
20 *
21 * @return 模型数组,里面装的是微博模型
22 */
23
24 +(NSArray*)selectModelDataWith:(StatusParam*)param;
注:这里只实现两个数据库操作方法,一个添加数据,一个读取数据。
点m文件如下
1 /**
2 * 工具类第一次使用时会调用此方法,而且只调用一次
3 */
4 +(void)initialize
5 {
6 //创建数据库存放沙盒路径
7 NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
8 NSString *path1 = [path stringByAppendingPathComponent:@"statues.sqlite"];
9 //实例化数据库队列对象
10 _queue = [[FMDatabaseQueue alloc] initWithPath:path1];
11 //创表,除了主键id还有三个字段,token:授权登录的token idstr:微博id model:微博模型
12 [_queue inDatabase:^(FMDatabase *db) {
13 BOOL result =[db executeUpdate:@"create table if not exists s_statues(id integer primary key autoincrement,token text,idstr text,model blob);"];
14 if (result) {
15 NSLog(@"创表成功");
16 }
17 }];
18
19
20 }
21
22
23 /**
24 * 缓存数据模型
25 *
26 * @param status 数据模型
27 */
28
29 +(void)addModel:(CZStatus*)status
30 {
31 [_queue inDatabase:^(FMDatabase *db) {
32
33 NSString *token = [AccountTool account].access_token;
34 NSString *idstr = status.idstr;
35 //把模型通过归档转换成二进制数据
36 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:status];
37 //把数据插入数据库
38 [db executeUpdate:@"insert into s_statues(token,idstr,model) values(?,?,?);",token,idstr,data];
39
40
41 }];
42 }
43
44 /**
45 * 缓存数据模型
46 *
47 * @param array 要缓存的模型数组
48 */
49 +(void)addModelWithArray:(NSArray*)array
50 {
51 for (CZStatus *status in array) {
52 [self addModel:status];
53 }
54 }
55
56
57 /**
58 * 查询数据库
59 *
60 * @param param 参数模型
61 *
62 * @return 模型数组
63 */
64
65 +(NSArray*)selectModelDataWith:(StatusParam*)param
66 {
67 __block NSMutableArray *array = nil;
68 [_queue inDatabase:^(FMDatabase *db) {
69 array = [NSMutableArray array];
70 FMResultSet *set = nil;
71 NSNumber *count = param.count ? param.count : @20;
72 /**
73 * sql查询语句
74 *
75 * 条件1: where token = ? token一定要是当前登录token
76 条件2: idstr > ? or idstr <= ? 查询的微博id,如果since_id有值说明要查询更新的微博,如果Maxid 有值得,说明要查询更早的微博
77 * 条件3:order by idstr desc 按照字段dstr 降序排列
78 条件4:limit 0,? 限制查询的条数,此条件要放到最后,第一个数字指定查询到行的偏移量,设为0表示偏移量从第一条数据开始算起,设为1,表示偏移量从第二条数据开始算起,第二个数字是指定查询的数量
79 */
80
81 if (param.since_id) {
82 set = [db executeQuery:@"select *from s_statues where token = ? and idstr > ? order by idstr desc limit 0,?;",param.access_token,param.since_id,count];
83
84 }else if (param.max_id){
85 set = [db executeQuery:@"select *from s_statues where token = ? and idstr <= ? order by idstr desc limit 0,?;",param.access_token,param.max_id,count];
86 }else{
87 set = [db executeQuery:@"select *from s_statues where token = ? order by idstr desc limit 0,?;",param.access_token,count];
88 }
89
90
91 //遍历结果集
92 while (set.next) {
93 //取出模型数据
94 NSData *data = [set dataForColumn:@"model"];
95 //反归档
96 CZStatus *status = [NSKeyedUnarchiver unarchiveObjectWithData:data];
97 [array addObject:status];
98 }
99
100 }];
101 return array;
102 }
注:缓存的微博模型是一个oc对象,这里需要把它转换成二进制数据才能存入数据库。
2、使用工具类在网络请求方法中缓存数据,先查询数据库,如果有数据,则取数据库的数据,如果没有,再发送网络请求
1 /**
2 * 请求微博数据
3 *
4 * @param param 请求参数模型
5 * @param success 请求成功后的回调
6 * @param failure 请求失败后的回调
7 */
8
9 +(void)homeStatusWithParam:(StatusParam*)param success:(void(^)(StatusResult *result))success failure:(void(^)(NSError *error))failure
10 {
11 //缓存模型
12
13 //先查询数据库,如果有数据,则取数据库的数据,如果没有,再发送网络请求
14 NSArray *baseArray = [DataBaseTool selectModelDataWith:param];
15 if (baseArray.count ) {
16 StatusResult *result = [[StatusResult alloc] init];
17 result.statuses = baseArray;
18 if (success) {
19 success(result);
20 }
21
22 }else{
23
24 //param.keyValues 模型
25 [CZHttpTool getRequestWithUrl:@"https://api.weibo.com/2/statuses/home_timeline.json" params:param.keyValues success:^(id json) {
26 //把请求结果字典json 转换为模型数据StatusResult,让控制器完全面向模型开发
27 StatusResult *result = [StatusResult objectWithKeyValues:json];
28
29 //一请求成功,那到微博模型数据,存入数据库
30 [DataBaseTool addModelWithArray:result.statuses];
31
32
33 if (success) {
34 success(result);
35 }
36 } failure:^(NSError *error) {
37 if (failure) {
38 failure(error);
39 }
40 }];
41
42
43 }
44
45
注:objectWithKeyValues: 这个方法是mj的字典转模型框架——"MJExtension",有兴趣的朋友可以了解下。