1.前言
刚刚在玩雀魂,感觉发牌姬一点也不爱我,遂来写一下今天学习WCDB(https://github.com/Tencent/wcdb)的记录。很久之前就开始了移动端数据库框架的调研,在这之前,IOS端是使用的FMDB框架,但是这个框架已经很久没有更新维护了,并且还是手动拼接SQL语句,容易出错和被SQL注入,所以一直想换框架。在这里就想提出了几个要求:性能不能太弱、移动端通用、体积不能太大。首先是因为这是一个即时通讯IM项目,对于数据库的性能要求还是有的,所以不能太弱;其次是想着移动端通用,好方便维护和设计;最后就是体积,由于移动端的存储和数据流量性质,所以尽量小还是小。所以选中了腾讯微信开源的WCDB框架。
2.正文
首先使用Cocoapods依赖进来,其它方式可以参考(Home · Tencent/wcdb Wiki · GitHub),随后就进行entity的ORM绑定,结果在WCDB_IMPLEMENTATIO和WCDB_SYNTHESIZE的宏定义报错了,搜issues中就知道了是app code的bug(Problem with highlighting errors/ warnings in jetbrains AppCode source editor for WCDB_IMPLEMENTATION WCDB_SYNTHESIZE · Issue #569 · Tencent/wcdb · GitHub),经过本人尝试,确实是AppCode的bug,编译可以通过。无法解决,包括关闭Inspections都依然有提示,为此我使用了一个折中的办法,那就是先只使用WCDB_PROPERTY宏定义,可以正常编码,然后将上述两个报错的宏定义注释掉,等开发完成后在Xcode再恢复(也可以编写一个Build Phaese脚本)。
总算是可以开发了,我这里给出几个例子。
<1>最简单的获取全部
返回值是一个NSArray数组。
SELECT * FROM user;
auto * db = [[WCTDatabase alloc] initWithPath:path];
if(![db isOpened]){
return nil;
}
auto * result = [db getAllObjectsOfClass:User.class fromTable:@"user"];
<2>加上WHERE语句
SELECT * FROM user WHERE id = ?;
auto * result = [db getObjectsOfClass:User.class fromTable:@"user" where:User.id==userId];
<3>再加上OrderBy语句
SELECT * FROM user WHERE id = ? order by nickname;
auto * result = [db getObjectsOfClass:User.class fromTable:@"user" orderBy:User.nickname.order(WCTOrderedAscending)];
CURD大概就是如此了,还有一种链式调用(iOS/macOS - Objective-C - 基础类、CRUD与Transaction - 《WCDB - 腾讯开源的移动数据库框架》 - 书栈网 · BookStack),基本就可以使用了。但是一旦遇上复杂语句怎么呢?
这就需要用到WINQ功能了。直接上例子。
<1>比较灵活?
WCTResultList resultList = [User AllProperties];
WCDB::StatementSelect statementSelect = WCDB::StatementSelect()
.select(resultList, resultList.isDistinct()).from(@"user".UTF8String);
statementSelect.where(User.id == userId);
statementSelect.orderBy(User.id.order(WCTOrderedAscending));
if(limit){
statementSelect.limit(4);
}
auto *reuslt = [db prepare:statementSelect];
<2>另外一种,下面这个可以自动反序列化,比较好用
WCTSelect *wctSelect = [[[db prepareSelectObjectsOfClass:User.class fromTable:@"user"]
where:User.id == userId]
orderBy:User.id.order(WCTOrderedAscending)];
if (limit) {
[wctSelect limit:4];
}
auto *result= [wctSelect allObjects];
<3>获取所有table。
for (WCTValue *value in [db getOneColumnOnResult:WCTMaster.name fromTable:WCTMaster.TableName]) {
NSLog(value);
}
在使用当中还需要几个问题:
<1>编译报错
Since WCDB is an Objective-C++ framework, for those files in your project that includes WCDB, you should rename their extension .m to .mm.
该报错来自于WCDB.h头文件的25行,如果没有存在__cplusplus宏定义就会报错,大家可能会好奇,引用的文件已经全部改成.mm文件,怎么还会没有__cplusplus宏定义呢。最常见的就是pch文件,如果你的项目使用PCH文件,那么无论后缀是什么,都不会使用c++编译器。终极办法就是直接去看build log,找到报错哪一行的变异command,
CompileC /Users/yymjr/Library/Developer/Xcode/DerivedData/**/**.o /Users/**.mm normal arm64 objective-c++ com.apple.compilers.llvm.clang.1_0.compiler
如果没有objective-c++,那么就代表不是c++编译器,自行修改即可。其他的似乎就是SQL语法问题了,没啥好说的啦。(如果后续还有什么问题,我会继续更新上来)