基本特性
- 易用,WCDB支持一句代码即可将数据取出并组合为object。
WINQ(WCDB语言集成查询):通过WINQ,开发者无须为了拼接SQL的字符串而写一大坨胶水代码。
ORM(Object Relational Mapping):WCDB支持灵活、易用的ORM。开发者可以很便捷地定义表、索引、约束,并进行增删改查操作。
[database getObjectsOfClass:WCTSampleConvenient.class
fromTable:tableName
where:WCTSampleConvenient.intValue>=10
limit:20];
- 高效,WCDB通过框架层和sqlcipher源码优化,使其更高效的表现。
- 多线程高并发:WCDB支持多线程读与读、读与写并发执行,写与写串行执行。
批量写操作性能测试:
更多关于WCDB的性能数据,请参考benchmark。
-
完整,WCDB覆盖了数据库相关各种场景的所需功能。
- 加密:WCDB提供基于SQLCipher的数据库加密。
- 损坏修复:WCDB内建了Repair Kit用于修复损坏的数据库。
- 反注入:WCDB内建了对SQL注入的保护。
通过cocoapods安装
- 先安装Cocoapods。
- 通过 pod repo update 更新WCDB的cocoapods版本。
- 在Podfile对应的target中,添加pod 'WCDB',并执行pod install。
- 在项目中使用CocoaPods生成的.xcworkspace运行工程。
- 在你的代码文件头引入头文件#import <WCDB/WCDB.h>。
- 由于WCDB是基于Objective-C++,因此需要将引用WCDB的源文件后缀.m改为.mm。
在这里需要说明的一点是,在iOS 11中,该库有一个bug修复,所以需要在pod中指定该库的地址,并且指定分支master.
target 'WCDBDemo' do
platform:ios,"8.0"
pod 'WCDB',git: 'https://github.com/Tencent/wcdb.git' , branch: 'master'
pod 'YYModel'
end
将一个已有的OC类进行QRM绑定的过程
- 定义该类遵守WCTTableCoding协议,可以在类声明上定义,也可以通过文件模版在category内定义。
这里推荐大家使用第二种,通过文件模板在category内定义,为什么要这样做,就是为了隔离Objective-C++代码
WCDB基于WINQ,引入了Objective-C++代码,所以对于引入了WCDB的源文件,都需要把后缀.m改为.mm,为减少影响范围,可以通过Objective-C的category特性将其隔离,达到只在model层使用Objective-C++编译,而不影响Controller和View。这一点在
Wiki中是有提到的,这样做的好处是不知道大家都有没有理解,这么说,要是你通过第一种方法,不通过category定义,而是选择了在类声明中写,这样的话Message.h 中就需要有宏WCDB_PROPERTY,这样你就在Message.h使用了WCDB的代码,当你把Message.h在其他Controller/View中引用的时候,那相应的Controller/View的.m就需要修改成.mm 。造成不必要的工作,但你用第二种方法写的时候,你就发现在Message.h中是没有任何的关于WCDB的代码的,后面你引用也不需要再去修改!希望大家理解这里
使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段(也就是把你的表里面需要的字段在这里用这宏声明一次)
使用WCDB_IMPLEMENTATIO宏在类文件定义绑定到数据库表的类(把这个类绑定到数据库的表,你会在下面创建数据库的时候创建相应的表,表会和类绑定)
使用WCDB_SYNTHESIZE宏在类文件定义绑定到数据库表的类(第二步声明了表需要的字段,第三步绑定了表中的类,第四步就等于把表和字段绑定)
创建model
Message.h
@interface Message : NSObject
@property int localID;
@property(retain) NSString *content;
@property(retain) NSDate *createTime;
@property(retain) NSDate *modifiedTime;
@end
Message.mm
@implementation Message
// 利用这个宏定义绑定到表的类
WCDB_IMPLEMENTATION(Message)
// 下面四个宏定义绑定到表中的字段
WCDB_SYNTHESIZE(Message, localID)
WCDB_SYNTHESIZE(Message, content)
WCDB_SYNTHESIZE(Message, createTime)
WCDB_SYNTHESIZE(Message, modifiedTime)
// 约束宏定义数据库的主键
WCDB_PRIMARY(Message, localID)
// 定义数据库的索引属性,它直接定义createTime字段为索引
// 同时 WCDB 会将表名 + "_index" 作为该索引的名称
WCDB_INDEX(Message, "_index", createTime)
@end
Message+WCTTableCoding.h
#import "Message.h"
#import <WCDB/WCDB.h>
@interface Message (WCTTableCoding) <WCTTableCoding>
// 需要绑定到表中的字段在这里声明,在.mm中去绑定
WCDB_PROPERTY(localID)
WCDB_PROPERTY(content)
WCDB_PROPERTY(createTime)
WCDB_PROPERTY(modifiedTime)
@end
创建数据库
//获取沙盒根目录
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 文件路径
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"model.sqlite"];
NSLog(@"path = %@",filePath);
database = [[WCTDatabase alloc]initWithPath:filePath];
// 数据库加密
NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
[database setCipherKey:password];
//测试数据库是否能够打开
if ([database canOpen]) {
// WCDB大量使用延迟初始化(Lazy initialization)的方式管理对象,因此SQLite连接会在第一次被访问时被打开。开发者不需要手动打开数据库。
// 先判断表是不是已经存在
if ([database isOpened]) {
if ([database isTableExists:tableName]) {
NSLog(@"表已经存在");
}else {
[database createTableAndIndexesOfName:tableName withClass:Message.class];
}
}
插入数据
Message *message = [[Message alloc] init];
message.localID = 1;
message.content = @"Hello, WCDB!";
message.createTime = [NSDate date];
message.modifiedTime = [NSDate date];
/*
INSERT INTO message(localID, content, createTime, modifiedTime)
VALUES(1, "Hello, WCDB!", 1496396165, 1496396165);
*/
[database insertObject:message into:@"message"];
更新数据
//UPDATE message SET content="Hello, Wechat!";
Message *message = [[Message alloc] init];
message.content = @"Hello, Wechat!";
//下面这句在17号的时候和微信团队的人在学习群里面沟通过,这个方法确实是不存在的,使用教程应该会更新,要是没更新注意这个方法
//BOOL result = [database updateTable:@"message" onProperties:Message.content withObject:message];
[database updateAllRowsInTable:@"message" onProperty:Message.content withObject:message];
查询数据
//SELECT * FROM message ORDER BY localID
NSArray<Message *> * message = [database getObjectsOfClass:Message.class fromTable:@"message" orderBy:Message.localID.order()];
NSLog(@">>>> %@",message);
删除数据
[database deleteObjectsFromTable:@"message" where:Message.localID > 0];
WCTDatabase 事务操作,利用WCTTransaction
BOOL ret = [database beginTransaction];
ret = [self insertMessage];
if (ret) {
[database commitTransaction];
}else
[database rollbackTransaction];
return ret;
使用Block处理事务
BOOL commit = [database runTransaction:^BOOL{
BOOL ret = [self insertMessage];
if (ret) {
return YES;
}else
return NO;
} event:^(WCTTransactionEvent event) {
NSLog(@"Event %d", event);
}];
return commit;