Osheep

时光不回头,当下最重要。

iOS实录10:iOS中的数据存储方案之LevelDB

[这是第10篇]

导语:Objective-LevelDB是基于Google’s LevelDB实现的Objective-C数据库,能快速实现key-value存储。根据项目的情况,基于Objective-LevelDB实现QSLevelDB,完成数据Model的存取和更新。

一、背景

1、由于项目中需要存储的数据,绝大部分不涉及查询、删除、插入等操作,只需要完成数据的写入读取全局更新即可。对于这部分数据,使用Objective-LevelDB这样的key-value存储再适合不过。

2、需要缓存的数据绝大部分都来自服务器,客户端从服务器获取JSON数据,通过模型转换得到Model对象。这些Model对象是我们根据JSON数据格式定义的Objective-C类的对象。一般来说,iOS不支持直接将自定义Model对象缓存到磁盘中,需要使用NSKeyedArchiver序列化Model,再存入磁盘;读取时候,使用NSKeyedUnarchiver来反序列化,从磁盘中获取Model

3、项目中所有自定义的Model类都继承了QSBaseModel,而QSBaseModel已经实现了Model的自动序列化和反序列化【这部分详见iOS进阶1:从YYModel源码看模型转换】。

二、源码实现

1、项目中需要引入YYModel 和 Objective-LevelDB 这两个第三方库
#LevelDB
pod 'Objective-LevelDB'
#YYModel
pod 'YYModel'
2、QSBaseModel部分源码
//QSBaseModel.h
#import <UIKit/UIKit.h>

@interface QSBaseModel : NSObject<NSCoding>

@property (nonatomic,assign)NSInteger updateTimeStamp; //更新model的时间戳

@end

//QSBaseModel.m
#import "QSBaseModel.h"
#import "YYModel.h"

@implementation QSBaseModel

//其他略
#pragma mark - 序列化和反序列化
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [self yy_modelEncodeWithCoder:aCoder];
}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
    return [self yy_modelInitWithCoder:aDecoder];
}

@end

说明1:通过YYModel,QSBaseModel实现了序列化和反序列化方法,直接继承QSBaseModel,默认实现了序列化和反序列化方法(很方便,是不是?)。

说明2:QSBaseModel增加了属性updateTimeStamp,用来记录Model存入LevelDB的时间

3、QSLevelDB源码(.h部分)
//QSLevelDB.h
 /**
 存储的更新策略
 */
typedef NS_ENUM(NSInteger,QSLevelDBUpdatePolicy){

    QSLevelDBUpdatePolicyLowest, //最低 -- 7 * 24hour后更新
    QSLevelDBUpdatePolicyLow ,   //低  -- 24hour后更新
    QSLevelDBUpdatePolicyMiddle, //中 -- 1hour后更新
    QSLevelDBUpdatePolicyHight,  //高  -- 1min后更新
    QSLevelDBUpdatePolicyHightest,  //最高 -- 10s后更新
};

@interface QSLevelDB : NSObject

#pragma mark - 初始化
- (instancetype)initWithDBName:(NSString *)dbName;

- (instancetype)initWithDBName:(NSString *)dbName
              updatePolicy:(QSLevelDBUpdatePolicy)updatePolicy;

- (instancetype)initWithDBName:(NSString *)dbName
            updateInterval:(NSTimeInterval) updateInterval;

#pragma mark - 存 和 取model
- (void)setObject:(id)model forKey:(NSString *)modelKey;

- (QSBaseModel *)objectForKey:(NSString *)modelKey;

#pragma mark - 删除Object & db
- (void)removeObjectForKey:(NSString *)modelKey;

- (void)removeObjectsForKeys:(NSArray *)modelKeyArray;

- (void)removeAllObjects;

- (void)deleteDatabaseFromDisk;

#pragma mark - 静态方法 用于删除指定数据库 和 所有数据库
+ (void)deleteAllDBFromDisk;

+ (void)deleteAllDBFromDiskWithComplete:(void(^)())completedBlock;

+ (void)deleteDatabaseFromDiskWithName:(NSString *)dbName;

+ (void)deleteDatabaseFromDiskWithName:(NSString *)dbName complete:(void(^)())completedBlock;

@end

说明1:QSLevelDBUpdatePolicy定义不同优先级的更新策略,对应不同数据存储的有效时间,当数据Model的存储时间超过指定的有效时间,数据会被清除。

说明2:QSLevelDB的初始化方法 – (instancetype)initWithDBName:updatePolicy:中提供了配置更新策略的参数(updatePolicy),如果对已经定义的更新策略不满意,可以使用- (instancetype)initWithDBName:updateInterval:方法配置更新有效时间(updateInterval,以s为单位)。

说明3:项目中有清除缓存的需要,通过QSLevelDB的静态方法可以实现对指定LevelDB 和 所有LevelDB的删除

4、QSLevelDB的使用

1) 自定义Model类

#pragma mark - QSBookModel & QSUserModel
@interface QSBookModel : QSBaseModel

@property (nonatomic,copy)NSString *name;
@property (nonatomic,assign)CGFloat price;

@end

@interface QSUserModel : QSBaseModel

@property (nonatomic,strong)QSBookModel *book;
@property (nonatomic,copy)NSString *userName;

@end

@implementation QSBookModel

@end

@implementation QSUserModel

@end

2) QSLevelDB使用

QSBookModel *book = [QSBookModel new];
book.name = @"一本书";
book.price = 18.5f;

QSUserModel *user = [[QSUserModel alloc]init];
user.book = book;
user.userName = @"王五";

NSString *dbName = @"userdb";
NSString *modelKey = @"user";

//1、初始化
QSLevelDB *db = [[QSLevelDB alloc]initWithDBName:dbName updatePolicy:QSLevelDBUpdatePolicyLow];

//2、存数据
[db setObject:user forKey:modelKey];

//3、读数据
NSLog(@"user model: %@", [db objectForKey:modelKey]);

//4、删除数据库
[QSLevelDB deleteDatabaseFromDiskWithName:dbName complete:^{
    NSLog(@"%@数据库删除了",dbName);
}];

3) 效果图

《iOS实录10:iOS中的数据存储方案之LevelDB》

效果图.png

三、写在最后

  • QSLevelDB仅仅封装了Objective-LevelDB存取数据的功能,Objective-LevelDB还支持枚举、快照(LDBSnapshot)和事务操作(LDBWriteBatch),具体使用参考Objective-LevelDB

  • 源码 : QSUseLevelDBDemo

点赞