通过《iOS开发通过微信学习WCDB(一)》这篇博客,相信大家对WCDB已经有了一个简单的了解和认识。这篇文章主要是为了进一步深入的学习
###数据库加密
上篇文章中提到了,自己在刚开始使用的时候没有效果,后来通过和WCDB的作者联系,了解到内容如下:WCDB如果要使用加密功能,必须在创建数据库后,没有存储数据之前,代码如下:
- (void)encryptDBData{
NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
[self.database setCipherKey:password];
}
执行完配置CipherKey
的操作之后,然后再往数据库中插入数据,这个时候数据就被加密了。而如果之前没有使用加密功能的话,如果想要使用加密功能的话,需要把数据从原来的数据库中读取出来,然后新建一个数据库,然后配置CipherKey
,将老数据库中的数据插入新数据即可。另外由于WCDB使用了配置CipherKey
的概念,只要配置了CipherKey
,WCDB内部自动实现了加密解密的功能。
###删除数据库中的表
- (void)deleteTable{
[self.database dropTableOfName:@"message"];//其中message为表的名字,删除表后,message表中存储的数据也一块被删除掉了。
}
###数据库中添加列
- (void)addTableColumn{
[self.database addColumn:Message.age.def(WCTColumnTypeInteger64) forTable:@"message"];
}
注:以上面的代码为例,添加列的时候,需要在Message.h
中把属性加上,代码如下:
@property(nonatomic, assign) NSInteger age;
在Message.mm
中把下面的代码添加上:
WCDB_SYNTHESIZE(Message, age)
在Message+WCTTableCoding.h
中需要实现如下代码:
WCDB_PROPERTY(age)
###根据指定条件创建表
在实际的开发过程中,我们有的时候对于数据模型的property,并不是每一个都要保存到数据库中的,对于这种情况,我们直接使用《iOS开发通过微信学习WCDB(一)》中创建表的操作就不会太合适了,针对这种情况,我们可以选择自定义一些条件来创建表,具体代码如下:
[self.database createTableOfName:@"TestModel" withColumnDefList:{TestModel.modelID.def(WCTColumnTypeInteger64)}];//这里可以添加多列
NSString *indexSubfix = @"_index";
NSString *indexName = [@"TestModel" stringByAppendingString:indexSubfix];
[self.database createIndexOfName:@"TestModel_index" withIndexList:{TestModel.modelID.index()} forTable:@"TestModel"];//这里用来设置index字端。
###数据库的恢复
WCDB提供了数据库的恢复功能,在数据库损坏的时候能够过进行修复,这个功能非常的棒,我这边进行了尝试,发现效果还是不错的,但是也有一些坑点。这里就给大家说一下。
####坑点一,数据库创建时数据库的名字不能有sqlite
的后缀名
刚开始自己创建数据库的时候数据库的名字是testDB.sqlite
带有sqlite的后缀名,在执行,增、删、查、改的操作都没有问题, 但是在执行恢复操作的时候却没有恢复成功。
####坑点二,数据库创建后需要执行备份的操作
数据库创建后需要执行备份的操作,具体如下:
NSData *backupCipher = [@"backupCipher" dataUsingEncoding:NSASCIIStringEncoding];
[self.database backupWithCipher:backupCipher];
坑点说完了,下面大家可以看一下数据库恢复的代码:
- (void)repairDataBase{
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];//目标数据库的路径
NSString *path = [NSString stringWithFormat:@"%@/testDB",docDir];
[self.database close:^{//模拟数据库损坏的操作
FILE *file = fopen(path.UTF8String, "rb+");
unsigned char *zeroPage = new unsigned char[100];
memset(zeroPage, 0, 100);
fwrite(zeroPage, 100, 1, file);
fclose(file);
}];
NSLog(@"The count of objects corrupted: %lu", [self.database getAllObjectsOfClass:Message.class fromTable:@"message"].count);
NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
NSData *backupCipher = [@"backupCipher" dataUsingEncoding:NSASCIIStringEncoding];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *recoverPath = [NSString stringWithFormat:@"%@/recoverDB",docDir];//临时恢复的数据库的路径
WCTDatabase * recover = [[WCTDatabase alloc] initWithPath:recoverPath];
NSData * password = [ @"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
NSData * backupPassword = [ @"MyBackupPassword" dataUsingEncoding:NSASCIIStringEncoding];
int pageSize = 4096 ; // iOS上的默认值为4096,macOS上的默认值为1024。
[self.database close:^ {
BOOL status = [recover recoverFromPath:path
withPageSize:pageSize
backupCipher:backupCipher
databaseCipher:password];
NSLog(@"The count of objects reCovered: %lu", [recover getAllObjectsOfClass:Message.class fromTable:@"message"].count);
}];
});
}
###数据库中的事务
在数据库中,事务可以说是高级玩法啊,能够帮助我们解决复杂的数据库操作处理。关于事务的详细解释可以参考百度百科。在实际的工作过程中,我们会遇到某个操作依赖于对数据库的复合处理,等处理所有的数据都数据成功后,才可以执行我们接下来的操作,否则就回滚。这种情况下事务就派上用场了。我写了一个简单的代码如下:
BOOL status = [self.database beginTransaction];
Message *message = [[Message alloc] init];
message.localID = 10000;
message.content = @"Hello, Jack!!!";
message.createTime = [NSDate date];
message.modifiedTime = [NSDate date];
BOOL ret = [self.database insertObject:message
into:@"message"];
if (ret) {
ret = [self.database commitTransaction];//只有commit过了,对数据库的操作才会真正生效。
} else {
ret = [self.database rollbackTransaction];
}
}
另外WCDB提供了一个批量插入数据的一个方法,里面用到了内置的事物,具体代码如下:
NSMutableArray *messages = [NSMutableArray new];
for (int i = 0; i<100; i++) {
Message *message = [[Message alloc] init];
message.localID = i;
message.content = @"Hello, Jack!!!";
message.createTime = [NSDate date];
message.modifiedTime = [NSDate date];
[messages addObject:message];
}
[self.database insertObjects:messages into:@"message"];
更多优质文章,可以微信扫码关注: