美文网首页
项目中数据缓存以及FMDB的使用

项目中数据缓存以及FMDB的使用

作者: 彡廿 | 来源:发表于2016-09-19 18:43 被阅读411次

公司项目是用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。

相关文章

  • 项目中数据缓存以及FMDB的使用

    公司项目是用cocospod管理的第三方库:在podfile文件中加入 pod 'FMDB', '~> 2.6.2...

  • SYCacheManager缓存数据操作

    SYCacheManager使用FMDB、LKDB进行二次封装,缓存数据。 FMDB的基本使用使用FMDataba...

  • Android性能优化-缓存的使用

    前言 最近又对数据缓存有了新的认识,所以来记录下我对缓存的理解,以及我在项目中是如何使用的。 为什么需要数据缓存 ...

  • 缓存模型到数据库中

    缓存使用的数据库。使用第三方FMDB。创建一个继承自NSObject类的文件去封装管理缓存的操作。增删改查。数据模...

  • iOS 本地购物车缓存&应用于实际项目中

    前言:enmmmmm......之前写了iOS 购物车本地缓存基于FMDB的实现&Demo,但是当真正结合使用到项...

  • iOS FMDB数据库实现增删改查

    FMDB是一个轻量级的数据库,用于将网络资源存储在本地。项目中使用 ARC 还是 MRC,对使用 FMDB 都没有...

  • 项目中常用的 iOS 第三方库

    数据相关 Haneke:数据缓存,包括 UIImage、NSData、JSON、String…… FMDB:�SQ...

  • FMDB的使用方法

    FMDB是Objective-C中对SQLite的封装库,使用FMDB可以很方便地在项目中对数据库进行管理。 FM...

  • 数据缓存

    项目中需要在没有网络的时候也显示数据,所以需要进行缓存。开始想用FMDB来做,后来有些不好操作,最终决定用NSKe...

  • 使用FMDB做离线缓存的例子(iOS)

    本文以仿微博的应用为基础,实现使用FMDB做离线缓存 设计思路: 分析加载微博过程: 尝试从沙盒加载缓存数据 有缓...

网友评论

      本文标题:项目中数据缓存以及FMDB的使用

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