离线缓存有多种方案,
一.什么是离线缓存?
离线缓存就是把用户访问过的数据存到本地的数据库中,下次打开App时首先展示上次查阅过得数据(如同微信),然后再刷新请求网络获取新的数据。
以新浪微博请求网络流程图为例:
思考一个问题,本地缓存需要创建多少张表,保存哪些内容呢?以新浪微博的一条微博为例:
第一种思路:
设计三张表,用户表,微博内容表,图片表(包含缩略图、中等图、大图等)
第二种思路:
为了简单,只用一张表,将服务器接口所返回的json数据直接存入表中,用的时候只需从表中解析即可 。
表结构设计:
access_token:一个access_token代表一个账号,如果一个用户有多个账号,则每个账号对应不同的缓存数据,即用来处理多账号登陆的问题。
二.离线缓存项目中实现
第一次网络请求后,存在缓存,下次进入后直接从缓存中获取数据。
// IWStatusTool.m
// ItcastWeibo
//
// Created by kaiyi on 16-6-3.
// Copyright (c) 2016年 itcast. All rights reserved.
#import "IWStatusCacheTool.h"
+(void)homeStatusesWithParam:(IWHomeStatusesParam *)param success:(void (^)(IWHomeStatusesResult *))success failure:(void (^)(NSError *))failure
{
// 1.先从缓存里边加载
NSArray *dicArray = [IWStatusCacheTool statuesWithParam:param];
if(dicArray.count){ // 有缓存
// 传递了block
if (success) {
IWHomeStatusesResult *result = [[IWHomeStatusesResult alloc] init];
result.statuses = [IWStatus objectArrayWithKeyValuesArray:dicArray];
success(result);
}
}
else
{
[IWHttpTool getWithURL:@"https://api.weibo.com/2/statuses/home_timeline.json" params:param.keyValues success:^(id json)
{
// 缓存 -[2016-07-09 add]
[IWStatusCacheTool addStatuses:json[@"statuses"]];
// NSArray *dictArray = json[@"status"];
// 请求成功后,新浪返回类型为字典的json,这里需要将字典转为模型
if(success){
IWHomeStatusesResult *result = [IWHomeStatusesResult objectWithKeyValues:json];
success(result);
}
} failure:^(NSError *error) {
if(failure){
failure(error);
}
}];
}
}
封装一个离线cache的工具类:
IWStatusCacheTool.m
//
// IWStatusCacheTool.m
// ItcastWeibo
//
// Created by kaiyi on 16-7-9.
// Copyright (c) 2016年 itcast. All rights reserved.
//
#import "IWStatusCacheTool.h"
#import "IWAccount.h"
#import "IWAccountTool.h"
#import "FMDB.h"
@implementation IWStatusCacheTool
static FMDatabaseQueue *_queue;
+(void)initialize{
// 0.获得沙盒中的数据库文件名
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"statuses.sqlite"];
// 1.创建队列
_queue = [FMDatabaseQueue databaseQueueWithPath:path];
// 2.创表
[_queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"create table if not exists t_status (id integer primary key autoincrement, access_token text, idstr text, dict blob);"];
}];
}
+(void)addStatus:(NSDictionary *)dict
{
[_queue inDatabase:^(FMDatabase *db) {
NSString *accessToken = [IWAccountTool account].access_token;
NSString *idstr = dict[@"idstr"];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict];
[db executeUpdate:@"insert into t_status (access_token, idstr, dict) values(?,?,?)", accessToken, idstr, data];
}];
}
+(void)addStatuses:(NSArray *)dictArray
{
for(NSDictionary *dict in dictArray){
[self addStatus:dict];
}
}
+(NSArray *)statuesWithParam:(IWHomeStatusesParam *)param
{
// 1.定义数组
__block NSMutableArray *dictArray = nil;
// 2.使用数据库
[_queue inDatabase:^(FMDatabase *db) {
// 创建数组
dictArray = [NSMutableArray array];
// accessToken
NSString *accessToken = [IWAccountTool account].access_token;
FMResultSet *rs = nil;
if (param.since_id) { // 如果有since_id
rs = [db executeQuery:@"select * from t_status where access_token = ? and idstr > ? order by idstr desc limit 0,?;", accessToken, param.since_id, param.count];
} else if (param.max_id) { // 如果有max_id
rs = [db executeQuery:@"select * from t_status where access_token = ? and idstr <= ? order by idstr desc limit 0,?;", accessToken, param.max_id, param.count];
} else { // 如果没有since_id和max_id
rs = [db executeQuery:@"select * from t_status where access_token = ? order by idstr desc limit 0,?;", accessToken, param.count];
}
while(rs.next){
NSData *data = [rs dataForColumn:@"dict"];
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[dictArray addObject:dict];
}
}];
return dictArray;
}
@end
项目源代码,请访问github获取微博项目源代码github
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。