iOS CouchBaseLite的简单封装和简单使用

简介

现在数据库方面的技术很多,也很成熟.但是很多公司也会有很奇怪的需求,明确你要使用什么技术.在数据量很多的时候,不能使用传统数据库的情况下,CouchBaseLite是一个很不错的选择.最起码比本地存储之类的方便,快捷,可以存储数据量比较大的数据,使用方法有点类似数据库.也称作NoSQL的存储方式.
Couchbase Lite 是一个为满足在线和离线的移动应用所开发的超轻量的,可靠的,并且安全的JSON数据库。即使在最不确定的网络条件下,亦可以给您的移动应用提供富有成效的和可靠的信誉。除此之外,’同步门户’功能亦可以提供协作, 社交互动或者是用户的更新。
官方DemoGitHub地址

环境配置

直通车(方便大家直接访问~)
或者按照下面的方法:

  • (1)我们先进去官网
    image
  • (2)点击进去,然后点击,install instructions(安装说明)
image
  • (3)就看到我们需要看到的内容啦. 然后选择我们的iOS
image

里面全部有介绍,怎么大家环境和使用方法.大家查看对应的说明搭建好环境就可以尝试使用了.


image

我的环境配置完成如下图(Xcode 9新建项目报错看最下面)


image

还得配置一些-objc


image
这些弄完就可以尝试编写了.

测试

我是直接基于原来的进行了一些简单的封装,在这里感谢@天梯传说@汪司机,给我很大的帮助.

  • (1)在APPdelegate中启动数据库操作,也可以在你们想要的位置
/*打开或者创建数据库(一般在APPdelegate中)*/
    [DatabaseSetupUtil databaseOpenOrCreate];
  • (2)引入文件


    image
  • (3)建立model层,自己定义了一些方法和变量,可以根据不用的需求定义不同.
    .h文件
#define UserDataPackageCollectionName @"UserDataPackage"
/**
 用户资料model实体
 作用: 主要是存储一些用户信息
 */
@interface UserDataDBModel : DBModelBase
/*-----可以定义字典或者数组类型,demo不做举例------*/
@property (nonatomic,strong) NSString* resident;     //居民姓名
@property (nonatomic,strong) NSString* mobile;      //居民手机号码
@property (nonatomic,strong) NSString* idno;        //居民身份证号码
@property (nonatomic,strong) NSNumber* status;       //状态:1、未上传,2、已上传
@property (nonatomic,strong) NSString* note;      //备注
@property (nonatomic,strong) NSString* crtime;  //创建时间

//根据实体id获取包数据
+ (UserDataDBModel*)getModelByPackageID:(NSString*)reportId;
//根据上上传状态值获取包数据(根据时间排序)
+ (NSArray*)getModelsByStatus:(NSNumber*)status;
//获取所有包数据(根据时间排序)
+ (NSArray*)getAllModels;

.m文件

- (instancetype)init
{
    self = [super init];
    if (self) {
        //文档所属的记录集
        self.collection = UserDataPackageCollectionName;
    }
    return self;
}

- (id)mutableCopy {
    UserDataDBModel* model = [[UserDataDBModel alloc] init];
    //这三个是必须的字段
    model._id = [self._id mutableCopy];
    model._rev = [self._rev mutableCopy];
    model.collection = [self.collection mutableCopy];
//中间代码省略...
    
    return model;
}

//实体转词典
- (NSDictionary*)toDictionary {
    NSMutableDictionary* dic = [NSMutableDictionary dictionary];
//中间代码省略...
    }

//词典转实体
+ (UserDataDBModel*)fromDictionary:(NSDictionary*)dictionary {
    UserDataDBModel* ret = [[UserDataDBModel alloc] init];
//中间代码省略...
}
    
   
#pragma mark -- 扩展方法

//根据体检报告id获取体检报告
+ (UserDataDBModel*)getModelByPackageID:(NSString*)reportId {
   //中间代码省略
}

//根据状态值获取体检报告
+ (NSArray*)getModelsByStatus:(NSNumber*)status {
  //中间代码省略
}

//获取所有体检报告
+ (NSArray*)getAllModels {
//中间代码省略
}
  • (4)ViewController中引入文件
#import "DatabaseSetupUtil.h"
#import "UserDataDBModel.h"

实现下面方法即可

//1.增加数据
- (void)addUserData {
    _model = [[UserDataDBModel alloc] init];
    _model.resident = @"张三";
    _model.mobile = @"123456789111";
    _model.idno = @"546456456575675";
    _model.note = @"假设是资料";
    _model.status = @0;
    _model.crtime = [self getCurrentUTCTime];
}

//保存
- (void)saveDate {
    if(![UserDataDBModel createDocument:_model]) {
        //失败
    }
    else {
        //成功
        NSArray* updateDatas = [UserDataDBModel getModelsByStatus:@0];
        for (UserDataDBModel* model in updateDatas) {
            NSLog(@"文档唯一性id: %@",model._id);
        }
    }
}

至于剩下的更新和删除的操作都是很简单的事情,直接DBModelBase父类的方法或者在model中重写一下父类的方法.

整体框架

[图片上传失败...(image-ad9ad9-1510651510810)]

下面的主要的.h文件的代码.
DBManager.h

/* 数据库 */
@property(strong,nonatomic,readonly) CBLDatabase*
database;

/* 是否启用数据库加密,默认不启用 */
@property(nonatomic) BOOL encrypt;

/**
 *  获取单例管理器对象
 */
+ (DBManager*)shareInstance;

/**
 *  根据数据库存放的路径以及数据库名字创建数据库
 * 参数 path :数据库存放的路径
 * 参数 name :数据库存放的路径
 * 返回值 :如果创建成功或者指定的路径已经存在指定名字的数据库则返回YES,否则返回NO
 */
-(BOOL)createDBWithPath:(NSString*)path  name:(NSString*)name;

/**
 *  根据数据库存放的路径以及数据库名字打开数据库
 * 参数 path :数据库存放的路径
 * 参数 name :数据库存放的路径
 * 返回值 :如果打开成功返回YES,否则返回NO
 */
-(BOOL)openDBWithPath:(NSString*)path  name:(NSString*)name;

/**
 *  删除数据库(必须先打开数据库才能执行删除操作)
 * 参数 path :数据库存放的路径
 * 参数 name :数据库存放的路径
 * 返回值 :如果如果成功或者不存在指定的路径指定名字的数据库则返回YES,否则返回NO
 */
-(BOOL)deleteDB;

/**
 *  执行事务性操作
 * 参数 block :事务block,一旦该block返回No即会执行回滚操作,返回Yes表示事务执行完成
 * 返回值 :如果成功则返回YES,否则返回NO
 */
- (BOOL)inTransaction: (BOOL(^)(void))block;

/**
 *  执行事务性操作(异步模式)
 * 参数 block :事务block,一旦该block返回No即会执行回滚操作,返回Yes表示事务执行完成
 * 参数 competition :完成回调block ,如果成功则返回YES,否则返回NO
 */
- (void)inTransaction: (BOOL(^)(void))block competition:(void (^)(BOOL result))competition;

SingleJobQueue.h

/**
 *  获取单例对象
 */
+ (SingleJobQueue*)shareInstance;

/**
 *  以block方式运行工作任务
 *
 *  @param jobBlock 工作任务block
 */
- (void)runWithJobBlock:(void (^)(void))jobBlock;

/**
 *  以block方式异步运行工作任务(不要问我为什么没有同步~)
 *
 *  @param jobBlock 工作任务block
 *  @param competition 完成回调block
 */
- (void)runAsyncJobWithJobBlock:(void (^)(void))jobBlock competition:(void (^)(void))competition;

DBModelBase.h

@property(strong,nonatomic) NSString* _id; //文档唯一性id
@property(strong,nonatomic) NSString* _rev; //文档版本
@property(strong,nonatomic) NSString* collection; //文档所属的记录集
@property(strong,nonatomic) NSMutableDictionary* extendFields;  //动态扩展字段

//实体转词典,子类必须重写
- (NSDictionary*)toDictionary;

//词典转实体
+ (id)fromDictionary:(NSDictionary*)dictionary;

//转换成服务端JSON
- (NSData*)toServerJSON;

/**
 *  根据指定的实体对象创建一个文档
 * 参数 model :继承自实体基类的具体实体实例
 * 返回值 :如果创建成功则返回文档id,否则返回nil
 */
+(NSString*)createDocument:(id)model;

/**
 *  根据指定的实体对象创建一个文档(异步模式)
 * 参数 model :继承自实体基类的具体实体实例
 * 参数 competition :完成回调block ,如果创建成功则返回文档id,否则返回nil
 */
+(void)createDocument:(id)model competition:(void (^)(NSString* docId))competition;

/**
 *  根据指定的实体对象创建一个文档(适合于在事务中执行)
 * 参数 model :继承自实体基类的具体实体实例
 * 返回值 :如果创建成功则返回文档id,否则返回nil
 */
+(NSString*)createDocumentForTransaction:(id)model;

/**
 *  删除指定id的文档
 * 参数 documentId :文档id
 * 返回值 :如果创建成功则返回YES,否则返回NO
 */
+(BOOL)deleteDocumentWithId:(NSString*)documentId;

/**
 *  删除指定id的文档(异步模式)
 * 参数 documentId :文档id
 * 参数 competition :完成回调block ,如果创建成功则返回YES,否则返回NO
 */
+(void)deleteDocumentWithId:(NSString*)documentId competition:(void (^)(BOOL result))competition;

/**
 *  删除指定id的文档(适合于在事务中执行)
 * 参数 documentId :文档id
 * 返回值 :如果创建成功则返回YES,否则返回NO
 */
+(BOOL)deleteDocumentForTransactionWithId:(NSString*)documentId;


/**
 *  根据指定的实体对象更新符合条件的文档
 * 参数 model :条件参数
 * 参数 newModel :新的文档值参数,继承自实体基类的具体实体实例
 * 返回值 :如果创建成功则返回YES,否则返回NO
 */
+(BOOL)updateDocument:(NSPredicate*)where newModel: (id) newModel;

/**
 *  根据指定的实体对象更新符合条件的文档(异步模式)
 * 参数 model :条件参数
 * 参数 newModel :新的文档值参数,继承自实体基类的具体实体实例
 * 参数 competition :完成回调block ,如果创建成功则返回YES,否则返回NO
 */
+(void)updateDocument:(NSPredicate*)where newModel: (id) newModel competition:(void (^)(BOOL result))competition;

/**
 *  根据指定的实体对象更新符合条件的文档
 * 参数 model :条件参数
 * 参数 newModel :新的文档值参数,继承自实体基类的具体实体实例
 * 返回值 :如果创建成功则返回YES,否则返回NO
 */
+(BOOL)updateDocumentForTransaction:(NSPredicate*)where newModel: (id) newModel;

/**
 *  根据指定的文档id查询文档
 * 参数 documentId :文档id
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例,否则返回nil
 */
+(id)getDocumentWithId:(NSString*)documentId;

/**
 *  根据指定的文档id查询文档(异步模式)
 * 参数 documentId :文档id
 * 参数 competition :完成回调block,如果查询成功则返回继承自实体基类的具体实体实例,否则返回nil
 */
+(void)getDocumentWithId:(NSString*)documentId competition:(void (^)(id doc))competition;

/**
 *  根据指定的文档id查询文档(适合于在事务中执行)
 * 参数 documentId :文档id
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例,否则返回nil
 */
+(id)getDocumentForTransactionWithId:(NSString*)documentId;

/**
 *  根据指定的实体对象获取符合条件的文档
 * 参数 select :获取字段参数
 * 参数 where :条件参数
 * 参数 orderBy :排序参数
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(NSArray*)getDocumentWithSelect: (nullable NSArray*)select where:(NSPredicate*)where orderBy:(nullable NSArray*)orderBy;

/**
 *  根据指定的实体对象获取符合条件的文档(异步模式)
 * 参数 select :获取字段参数
 * 参数 where :条件参数
 * 参数 orderBy :排序参数
 * 参数 competition :完成回调block,如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(void)getDocumentWithSelect: (nullable NSArray*)select where:(NSPredicate*)where orderBy:(nullable NSArray*)orderBy competition:(void (^)(NSArray*))competition;

/**
 *  根据指定的实体对象获取符合条件的文档(适合于在事务中执行)
 * 参数 select :获取字段参数
 * 参数 where :条件参数
 * 参数 orderBy :排序参数
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(NSArray*)getDocumentForTransactionWithSelect: (nullable NSArray*)select where: (NSPredicate*)where orderBy:(nullable NSArray*)orderBy;

/**
 *  根据指定的实体对象获取符合条件的文档
 * 参数 select : 获取字段参数
 * 参数 where : 条件参数
 * 参数 orderBy : 排序参数
 * 参数 skip : 跳过多少条
 * 参数 limit : 读取多少条
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(NSArray*)getDocumentWithSelect: (nullable NSArray*)select where:(NSPredicate*)where orderBy:(nullable NSArray*)orderBy skip:(NSInteger)skip limit:(NSInteger)limit;

/**
 *  根据指定的实体对象获取符合条件的文档(异步模式)
 * 参数 select : 获取字段参数
 * 参数 where : 条件参数
 * 参数 orderBy : 排序参数
 * 参数 skip : 跳过多少条
 * 参数 limit : 读取多少条
 * 参数 competition :完成回调block,如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(void)getDocumentWithSelect: (nullable NSArray*)select where:(NSPredicate*)where orderBy:(nullable NSArray*)orderBy skip:(NSInteger)skip limit:(NSInteger)limit competition:(void (^)(NSArray*))competition;

/**
 *  根据指定的实体对象获取符合条件的文档(适合于在事务中执行)
 * 参数 select : 获取字段参数
 * 参数 where : 条件参数
 * 参数 orderBy : 排序参数
 * 参数 skip : 跳过多少条
 * 参数 limit : 读取多少条
 * 返回值 :如果查询成功则返回继承自实体基类的具体实体实例数组,否则返回nil
 */
+(NSArray*)getDocumentForTransactionWithSelect: (nullable NSArray*)select where:(NSPredicate*)where orderBy:(nullable NSArray*)orderBy skip:(NSInteger)skip limit:(NSInteger)limit;

上面的主要是封装的部分方法和文件说明
具体的请查看demo

小结

这个CouchBaseLite个人觉得还是蛮好用的,简单粗暴...,和以往的数据库操作基本一样,也算是比较轻量级的存储了.
上面主要是自己的一些理解的封装,还有很多需要完善,目前只是简单的实现了部分功能,这个后面会逐渐完善的.有什么写错的,请大家指出,一起讨论.

话外篇

Xcode 9的,新建项目会报错,大家就按照下图取消这个就好啦


image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 参与:参与故名思议就是参与其中,我不由自主地觉得是团队协作的既视感。有一回公司组织了一次户外拓展,其中有一个叫“合...
    么么玄米茶阅读 151评论 0 1
  • 中午,看到丽丽在朋友圈发了一条状态,图片是放在盘里的两只炸鸡腿,金灿灿黄澄澄的。 配文是:哈哈哈哈,老公想用两只鸡...
    c小尘阅读 450评论 5 1
  • 天冷了 一个人在外 特别的孤独 而且想着一个不可能的人 他不来 我就要走了 点了外卖 这个地方不不算落后 就是找不...
    村里灯花阅读 182评论 0 0