公司项目是用cocospod管理的第三方库:
在podfile
文件中加入 pod 'FMDB', '~> 2.6.2'
引入FMDB就可以使用了
项目是新闻类的app,只有下拉刷新,缓存的思路:
屏幕快照 2016-09-19 下午6.14.22.png设计NIPNewsDatabase类来管理数据库文件
- 保存
- 查找
- 删除数据库文件
在保存的时候涉及到清除陈旧的数据,清除的思路:
- 设定缓存的时间长 maxTime
添加一个存储时间的字段,删除改频道下一周之前的数据
- 设定缓存的新闻数 dbMaxCount
计算当前频道下新闻数dbCount,如果dbCount > dbMaxCount,就删除旧的数据
这两种思路,我采用了第二种设定缓存的新闻数目,第一种更简单
NIPNewsDatabase.h
#import <Foundation/Foundation.h>
@interface NIPNewsDatabase : NSObject
/**
* 保存新闻数据到数据库
*
* @param json json
* @param categoryId 新闻的频道
*/
+ (void)saveData:(NSDictionary *)json categoryId:(NSInteger)categoryId;
/**
* 根据频道返回新闻数据
*
* @param categoryId 新闻频道
*/
+ (NSArray *)getJsonWithCategoryId:(NSInteger)categoryId;
/**
* 删除数据库
*/
+ (void)removeDatabase;
@end
NIPNewsDatabase.m
#import "NIPNewsDatabase.h"
#import "FMDB.h"
@implementation NIPNewsDatabase
static FMDatabase *_db;
#define path [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"newsApiResponse.sqlite"]
+ (void)initialize
{
// 1.打开数据库
_db = [FMDatabase databaseWithPath:path];
[_db open];
// 2.创表
[_db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_newsApiResponse (id integer PRIMARY KEY, newsApiResponse blob NOT NULL, categoryId integer NOT NULL ,time integer NOT NULL);"];
}
+ (NSArray *)getJsonWithCategoryId:(NSInteger)categoryId
{
NSString * categoryIdStr = [NSString stringWithFormat:@"%ld",(long)categoryId];
FMResultSet * set = [_db executeQuery:@"SELECT * FROM t_newsApiResponse WHERE categoryId=?;",categoryIdStr];
NSMutableArray * resultArr = [NSMutableArray array];
while (set.next) {
NSData * newsData = [set objectForColumnName:@"newsApiResponse"];
NSDictionary * result = [NSKeyedUnarchiver unarchiveObjectWithData:newsData];
[resultArr addObject:result];
}
return resultArr;
}
+ (void)saveData:(NSDictionary *)json categoryId:(NSInteger)categoryId
{
// 1.保存最新的数据
NSData * newsData = [NSKeyedArchiver archivedDataWithRootObject:json];
[_db executeUpdateWithFormat:@"INSERT INTO t_newsApiResponse(newsApiResponse, categoryId, time) VALUES (%@, %ld, %@);", newsData, (long)categoryId, @((NSInteger)[[NSDate date] timeIntervalSince1970])];
// 2.设置最大缓存数;
int dbMaxCount = 10;
// 3.获得数据库中的条数
int dbCount = 0;
NSMutableArray * dbIDs = [NSMutableArray array];
FMResultSet * set = [_db executeQuery:@"SELECT * FROM t_newsApiResponse WHERE categoryId = ?;",[NSString stringWithFormat:@"%ld",(long)categoryId]];
while (set.next) {
dbCount ++;
int ID = [set intForColumnIndex:0];
[dbIDs addObject:@(ID)];
}
// 4.删除多余的数据
if (dbCount > dbMaxCount) {
int beyondID = [dbIDs[dbCount-dbMaxCount] intValue];
NSString * deleteSql = [NSString stringWithFormat:@"DELETE FROM t_newsApiResponse WHERE categoryId = '%ld' AND id < '%d'",categoryId,beyondID];
if (![_db executeUpdate:deleteSql]) {
NIPLog(@"数据库删除失败");
}
}
}
+ (void)removeDatabase
{
NSFileManager * fileManager = [[NSFileManager alloc] init];
[fileManager removeItemAtPath:path error:nil];
}
在VC中
// 从数据中加载数据
- (void)loadDataFromeDB
{
// 进入界面先从数据库中取数据
NSArray * responses = [NIPNewsDatabase getJsonWithCategoryId:[self.categoryId integerValue]];
if (responses.count) {
for (NSDictionary * dict in responses) {
NSArray<NIPNews *> * array = [NIPNews mj_objectArrayWithKeyValuesArray:dict[@"News"]];
[self.newsArray addObjectsFromArray:array];
[self.tableView reloadData];
}
}else{ // 数据库中不存在数据,执行网络刷新
[self.tableView.mj_header beginRefreshing];
}
}
// 网络请求
- (void)loadNewsData
{
[NIPHttpManager.tasks makeObjectsPerformSelector:@selector(cancel)];
NSString * urlStr ;
NSMutableDictionary * param = [NSMutableDictionary dictionary];
if (self.categoryId.intValue == 0 && self.newsArray.count == 0) {
urlStr = @"News?count=15";
param = nil;
}
if (self.categoryId.intValue == 0 && self.newsArray.count) {
urlStr = @"News?fromUser=true";
param = nil;
}
if (self.categoryId.intValue && self.newsArray.count == 0) {
urlStr = @"News";
param[@"categoryId"] = self.categoryId;
param[@"count"] = @(15);
}
if (self.categoryId.intValue && self.newsArray.count) {
urlStr = @"News";
param[@"categoryId"] = self.categoryId;
param[@"count"] = @(8);
}
[NIPHttpManager GET:NIPURL(urlStr) parameters:param progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 保存到数据库
[NIPNewsDatabase saveData:responseObject categoryId:[self.categoryId integerValue]];
NSArray<NIPNews *> * array = [NIPNews mj_objectArrayWithKeyValuesArray:responseObject[@"News"]];
NSRange range = NSMakeRange(0, array.count);
NSIndexSet * set = [NSIndexSet indexSetWithIndexesInRange:range];
[self.newsArray insertObjects:array atIndexes:set];
[self.tableView reloadData];
[self showNewStatusCount:array.count];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self showNewStatusCount:0];
[self.tableView.mj_header endRefreshing];
}];
}
调试用了SimPholder 和 Navicat for SQLite两个软件
realm数据缓存新贵,性能高,操作简单。在json转模型的时候配合使用jsonmodel工具可以将复杂的json(嵌套多层)直接转成realm格式的model类,之前想尝试用realm做缓存的,因为模型都已经建好,不想再按照realm的格式改,所以就继续用了FMDB。
网友评论