微信数据存储WCDB for iOS/macOS
WCDB
WCDB是一个高效、完整、易用的移动数据库框架,基于SQLCipher,支持iOS, macOS。
WCDB for iOS/macOS
基本特性
易用,WCDB支持一句代码即可将数据取出并组合为object。
WINQ(WCDB语言集成查询):通过WINQ,开发者无须为了拼接SQL的字符串而写一大坨胶水代码。
ORM(Object Relational Mapping):WCDB支持灵活、易用的ORM。开发者可以很便捷地定义表、索引、约束,并进行增删改查操作。
[database getObjectsOfClass:WCTSampleConvenient.classfromTable:tableNamewhere:WCTSampleConvenient.intValue>=10limit:20];
高效,WCDB通过框架层和sqlcipher源码优化,使其更高效的表现。
多线程高并发:WCDB支持多线程读与读、读与写并发执行,写与写串行执行。
批量写操作性能测试:
更多关于WCDB的性能数据,请参考benchmark。
完整,WCDB覆盖了数据库相关各种场景的所需功能。
- 加密:WCDB提供基于SQLCipher的数据库加密。
- 损坏修复:WCDB内建了Repair Kit用于修复损坏的数据库。
- 反注入:WCDB内建了对SQL注入的保护。
基本要求
- WCDB支持iOS 7、macOS 10.9以上。
- WCDB需使用Xcode 8.0以上版本进行编译。
- 需使用Objective-C++。
通过CocoaPods安装,此处不介绍安装过程,感兴趣可以参考文章:http://www.cnblogs.com/HJiang/p/7228166.html
/*将一个已有的ObjC类进行ORM绑定的过程如下:定义该类遵循WCTTableCoding协议。可以在类声明上定义,也可以通过文件模版在category内定义。使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段。使用WCDB_IMPLEMENTATIO宏在类文件定义绑定到数据库表的类。使用WCDB_SYNTHESIZE宏在类文件定义需要绑定到数据库表的字段。*/
.实体类.
新建Message类
Message.h
#import <Foundation/Foundation.h>@interface Message : NSObject/*** 本地id*/ @property (nonatomic,assign) int localID;/*** 消息内容*/ @property (nonatomic, strong) NSString *content;/*** 创建时间*/ @property (nonatomic, strong) NSDate *createTime;/*** 最后更新时间*/ @property (nonatomic, strong) NSDate *modifiedTime;/*** 未读消息*/ @property (nonatomic,assign) int unused;@end
Message.mm
#import "Message.h" #import "Message+WCTTableCoding.h"@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)- (NSString *)description{return [NSString stringWithFormat:@"localID:%d content:%@ createTime:%@ modifiedTime:%@",_localID,_content,_createTime,_modifiedTime]; }@end
Message+WCTTableCoding.h Message分类
#import "Message.h" #import <WCDB/WCDB.h>@interface Message (WCTTableCoding) <WCTTableCoding>/*需要绑定到表中的字段在这里声明,在.mm中去绑定使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段。*/ WCDB_PROPERTY(localID) WCDB_PROPERTY(content) WCDB_PROPERTY(createTime) WCDB_PROPERTY(modifiedTime)@end
由于WCDB是基于Objective-C++,因此需要将引用WCDB的源文件后缀.m
改为.mm
所以Message.m需修改为.mm
数据库管理类
WCTDatabaseManager.h WCTDatabaseManager.mm
#import <Foundation/Foundation.h> @class WCTDatabase;@interface WCTDatabaseManager : NSObject+ (instancetype)shareInstance;- (WCTDatabase *)getDatabase;/**创建数据库@param tableName 表名称@return 是否创建成功*/ - (BOOL)creatDataBaseWithName:(NSString *)tableName;@end
#import "WCTDatabaseManager.h" #import "WCTDatabaseManager+DataBase.h" #import "Message.h" //#import "Message+WCTTableCoding.h"@interface WCTDatabaseManager() {WCTDatabase *database; }@end@implementation WCTDatabaseManager+ (instancetype)shareInstance{static WCTDatabaseManager * instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[WCTDatabaseManager alloc]init];});return instance; }- (NSString *)getDatabasePath{//获取沙盒根目录NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];// 文件路径NSString *filePath = [documentsPath stringByAppendingPathComponent:@"Wechat.sqlite"];return filePath; }- (WCTDatabase *)getDatabase{if(!database){NSString *filePath = [self getDatabasePath];NSLog(@"wChatDatapath = %@",filePath);database = [[WCTDatabase alloc] initWithPath:filePath];}return database; }-(BOOL)creatDataBaseWithName:(NSString *)tableName{[self getDatabase];// 数据库加密//NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];//[database setCipherKey:password];//测试数据库是否能够打开if ([database canOpen]) {// WCDB大量使用延迟初始化(Lazy initialization)的方式管理对象,因此SQLite连接会在第一次被访问时被打开。开发者不需要手动打开数据库。// 先判断表是不是已经存在if ([database isOpened]) {if ([database isTableExists:tableName]) {NSLog(@"表已经存在");return NO;}else{return [database createTableAndIndexesOfName:tableName withClass:Message.class];}}}return NO; }@end
WCTDatabaseManager+DataBase.h WCTDatabaseManager分类,引入WCDB头文件
#import <WCDB/WCDB.h>@interface WCTDatabaseManager (DataBase)@end
数据库操作类
#import <Foundation/Foundation.h> @class Message;@interface MessageDao : NSObject- (BOOL)insertMessage:(Message *)message;- (BOOL)insertMessageWithTransaction:(Message *)message;- (BOOL)insertMessageWithBlock:(Message *)message;- (BOOL)deleteMessage:(Message *)message;- (BOOL)updataMessage:(Message *)message;- (NSArray *)seleteMessages;@end
#import "MessageDao.h" #import "WCTDatabaseManager.h" #import <WCDB/WCDB.h> #import "Message.h" #import "Message+WCTTableCoding.h"#define kDataBase [[WCTDatabaseManager shareInstance] getDatabase]@implementation MessageDao- (BOOL)insertMessage:(Message *)message{return [kDataBase insertObject:message into:@"message"]; }// WCTDatabase 事务操作,利用WCTTransaction - (BOOL)insertMessageWithTransaction:(Message *)message{BOOL ret = [kDataBase beginTransaction];ret = [self insertMessage:message];if (ret) {[kDataBase commitTransaction];}else{[kDataBase rollbackTransaction];}return ret; }// 另一种事务处理方法Block - (BOOL)insertMessageWithBlock:(Message *)message{BOOL commit = [kDataBase runTransaction:^BOOL{BOOL ret = [self insertMessage:message];if (ret) {return YES;}else{return NO;}} event:^(WCTTransactionEvent event) {NSLog(@"Event %d", event);}];return commit; }- (BOOL)deleteMessage:(Message *)message{ // 删除//DELETE FROM message WHERE localID>0;return [kDataBase deleteObjectsFromTable:@"message" where:Message.localID > 0]; }- (BOOL)updataMessage:(Message *)message{//修改//UPDATE message SET content="Hello, Wechat!";return [kDataBase updateAllRowsInTable:@"message" onProperty:Message.content withObject:message]; }- (NSArray *)seleteMessage{//SELECT * FROM message ORDER BY localIDNSArray<Message *> * message = [kDataBase getObjectsOfClass:Message.class fromTable:@"message" orderBy:Message.localID.order()];return message; }@end
测试方法
---恢复内容结束---
WCDB
WCDB是一个高效、完整、易用的移动数据库框架,基于SQLCipher,支持iOS, macOS。
WCDB for iOS/macOS
基本特性
易用,WCDB支持一句代码即可将数据取出并组合为object。
WINQ(WCDB语言集成查询):通过WINQ,开发者无须为了拼接SQL的字符串而写一大坨胶水代码。
ORM(Object Relational Mapping):WCDB支持灵活、易用的ORM。开发者可以很便捷地定义表、索引、约束,并进行增删改查操作。
[database getObjectsOfClass:WCTSampleConvenient.classfromTable:tableNamewhere:WCTSampleConvenient.intValue>=10limit:20];
高效,WCDB通过框架层和sqlcipher源码优化,使其更高效的表现。
多线程高并发:WCDB支持多线程读与读、读与写并发执行,写与写串行执行。
批量写操作性能测试:
更多关于WCDB的性能数据,请参考benchmark。
完整,WCDB覆盖了数据库相关各种场景的所需功能。
- 加密:WCDB提供基于SQLCipher的数据库加密。
- 损坏修复:WCDB内建了Repair Kit用于修复损坏的数据库。
- 反注入:WCDB内建了对SQL注入的保护。
基本要求
- WCDB支持iOS 7、macOS 10.9以上。
- WCDB需使用Xcode 8.0以上版本进行编译。
- 需使用Objective-C++。
通过CocoaPods安装,此处不介绍安装过程,感兴趣可以参考文章:http://www.cnblogs.com/HJiang/p/7228166.html
/*
将一个已有的ObjC类进行ORM绑定的过程如下:
定义该类遵循WCTTableCoding协议。可以在类声明上定义,也可以通过文件模版在category内定义。
使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段。
使用WCDB_IMPLEMENTATIO宏在类文件定义绑定到数据库表的类。
使用WCDB_SYNTHESIZE宏在类文件定义需要绑定到数据库表的字段。
*/
以例子参考:
.实体类.
新建Message类
Message.h
#import <Foundation/Foundation.h>@interface Message : NSObject/*** 本地id*/ @property (nonatomic,assign) int localID;/*** 消息内容*/ @property (nonatomic, strong) NSString *content;/*** 创建时间*/ @property (nonatomic, strong) NSDate *createTime;/*** 最后更新时间*/ @property (nonatomic, strong) NSDate *modifiedTime;/*** 未读消息*/ @property (nonatomic,assign) int unused;@end
Message.mm
#import "Message.h" #import "Message+WCTTableCoding.h"@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)- (NSString *)description{return [NSString stringWithFormat:@"localID:%d content:%@ createTime:%@ modifiedTime:%@",_localID,_content,_createTime,_modifiedTime]; }@end
Message+WCTTableCoding.h Message分类
#import "Message.h" #import <WCDB/WCDB.h>@interface Message (WCTTableCoding) <WCTTableCoding>/*需要绑定到表中的字段在这里声明,在.mm中去绑定使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段。*/ WCDB_PROPERTY(localID) WCDB_PROPERTY(content) WCDB_PROPERTY(createTime) WCDB_PROPERTY(modifiedTime)@end
由于WCDB是基于Objective-C++,因此需要将引用WCDB的源文件后缀.m
改为.mm
所以Message.m需修改为.mm
数据库管理类
WCTDatabaseManager.h WCTDatabaseManager.mm
#import <Foundation/Foundation.h> @class WCTDatabase;@interface WCTDatabaseManager : NSObject+ (instancetype)shareInstance;- (WCTDatabase *)getDatabase;/**创建数据库@param tableName 表名称@return 是否创建成功*/ - (BOOL)creatDataBaseWithName:(NSString *)tableName;@end
#import "WCTDatabaseManager.h" #import "WCTDatabaseManager+DataBase.h" #import "Message.h" //#import "Message+WCTTableCoding.h"@interface WCTDatabaseManager() {WCTDatabase *database; }@end@implementation WCTDatabaseManager+ (instancetype)shareInstance{static WCTDatabaseManager * instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[WCTDatabaseManager alloc]init];});return instance; }- (NSString *)getDatabasePath{//获取沙盒根目录NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];// 文件路径NSString *filePath = [documentsPath stringByAppendingPathComponent:@"Wechat.sqlite"];return filePath; }- (WCTDatabase *)getDatabase{if(!database){NSString *filePath = [self getDatabasePath];NSLog(@"wChatDatapath = %@",filePath);database = [[WCTDatabase alloc] initWithPath:filePath];}return database; }-(BOOL)creatDataBaseWithName:(NSString *)tableName{[self getDatabase];// 数据库加密//NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];//[database setCipherKey:password];//测试数据库是否能够打开if ([database canOpen]) {// WCDB大量使用延迟初始化(Lazy initialization)的方式管理对象,因此SQLite连接会在第一次被访问时被打开。开发者不需要手动打开数据库。// 先判断表是不是已经存在if ([database isOpened]) {if ([database isTableExists:tableName]) {NSLog(@"表已经存在");return NO;}else{return [database createTableAndIndexesOfName:tableName withClass:Message.class];}}}return NO; }@end
WCTDatabaseManager+DataBase.h WCTDatabaseManager分类,引入WCDB头文件
#import <WCDB/WCDB.h>@interface WCTDatabaseManager (DataBase)@end
数据库操作类
#import <Foundation/Foundation.h> @class Message;@interface MessageDao : NSObject- (BOOL)insertMessage:(Message *)message;- (BOOL)insertMessageWithTransaction:(Message *)message;- (BOOL)insertMessageWithBlock:(Message *)message;- (BOOL)deleteMessage:(Message *)message;- (BOOL)updataMessage:(Message *)message;- (NSArray *)seleteMessages;@end
#import "MessageDao.h" #import "WCTDatabaseManager.h" #import <WCDB/WCDB.h> #import "Message.h" #import "Message+WCTTableCoding.h"#define kDataBase [[WCTDatabaseManager shareInstance] getDatabase]@implementation MessageDao- (BOOL)insertMessage:(Message *)message{return [kDataBase insertObject:message into:@"message"]; }// WCTDatabase 事务操作,利用WCTTransaction - (BOOL)insertMessageWithTransaction:(Message *)message{BOOL ret = [kDataBase beginTransaction];ret = [self insertMessage:message];if (ret) {[kDataBase commitTransaction];}else{[kDataBase rollbackTransaction];}return ret; }// 另一种事务处理方法Block - (BOOL)insertMessageWithBlock:(Message *)message{BOOL commit = [kDataBase runTransaction:^BOOL{BOOL ret = [self insertMessage:message];if (ret) {return YES;}else{return NO;}} event:^(WCTTransactionEvent event) {NSLog(@"Event %d", event);}];return commit; }- (BOOL)deleteMessage:(Message *)message{ // 删除//DELETE FROM message WHERE localID>0;return [kDataBase deleteObjectsFromTable:@"message" where:Message.localID > 0]; }- (BOOL)updataMessage:(Message *)message{//修改//UPDATE message SET content="Hello, Wechat!";return [kDataBase updateAllRowsInTable:@"message" onProperty:Message.content withObject:message]; }- (NSArray *)seleteMessage{//SELECT * FROM message ORDER BY localIDNSArray<Message *> * message = [kDataBase getObjectsOfClass:Message.class fromTable:@"message" orderBy:Message.localID.order()];return message; }@end
测试方法
#import "ViewController.h" #import "WCTDatabaseManager.h" #import "MessageDao.h" #import "Message.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad]; }- (IBAction)createDataBaseDidClick:(UIButton *)sender {BOOL result = [[WCTDatabaseManager shareInstance] creatDataBaseWithName:@"message"];NSLog(@"%@",((result == YES)?@"创建数据库成功":@"创建数据库失败")); }- (IBAction)insertBtnDidClick:(UIButton *)sender {MessageDao *messageDao = [[MessageDao alloc] init];Message *message = [[Message alloc] init];message.localID = 1;message.content = @"Hello, WCDB!";message.createTime = [NSDate date];message.modifiedTime = [NSDate date];[messageDao insertMessageWithTransaction:message]; }- (IBAction)updateBtnDidClick:(UIButton *)sender {MessageDao *messageDao = [[MessageDao alloc] init];Message *message = [[Message alloc] init];message.content = @"Hello, Wechat!";[messageDao updataMessage:message]; }- (IBAction)selectBtnDidClick:(UIButton *)sender {MessageDao *messageDao = [[MessageDao alloc] init];NSArray *messages = [messageDao seleteMessage];NSLog(@"%@",messages); }- (IBAction)deleteBtnDidClick:(UIButton *)sender {MessageDao *messageDao = [[MessageDao alloc] init];[messageDao deleteMessage:nil]; }@end
更多的查询操作后续更新.
转载于:https://www.cnblogs.com/HJiang/p/8260628.html
微信数据存储WCDB for iOS/macOS相关推荐
- 微信数据导出。(IOS 无加密)
code:https://github.com/Sunmile/study_note 我的代码笔记中 MMsaver exe:http://download.csdn.net/detail/oadam ...
- python 埋点 库_埋点全解 10 :数据存储
1.原理概述 为了最大限度的保证事件数据的准确性.完整性和及时性,数据采集 SDK 需要及时的将事件数据同步到服务端.但在某些 特殊情况下,比如手机处于断网环境,或者根据实际需求只能在 Wi-Fi 环 ...
- IOS数据存储 之WCDB (一)
IOS数据存储 之WCDB (一) 1. WCDB 简介 1.1 使用WCDB框架3大优势 1.2 WCDB 的一些基础概念 1.2.1 类字段绑定(ORM) 1.2.2 WINQ(WCDB语言集成查 ...
- IOS数据存储 之WCDB (二)WCDB.swift使用篇
IOS数据存储 之WCDB (二)WCDB.swift使用篇 1.WCDB.Swfit基础使用 1.1 WCDB.Swfit 简介 1.1.1 模型绑定 1.1.2 创建数据库与表 1.1.3 操作数 ...
- iOS开发 数据存储之WCDB的介绍
一.介绍 WCDB是一个高效.完整.易用的移动数据库框架,基于SQLCipher,支持iOS,macOS和Android 二.基本特性 易用,WCDB支持一句代码即可将数据取出并组合为object W ...
- iOS开发之数据存储
概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储, ...
- Unity 之 转微信小游戏本地数据存储方法分享
Unity 之 转微信小游戏本地数据存储 问题背景 微信小游戏读写本地文件 WebGL平台的一些限制 报错查看方法分享 问题背景 近期在将Unity转换为小游戏的时候发现在读写本地文件的时候,使用Ap ...
- IOS数据存储之文件沙盒存储
前言: 之前学习了数据存储的NSUserDefaults,归档和解档,对于项目开发中如果要存储一些文件,比如图片,音频,视频等文件的时候就需要用到文件存储了.文件沙盒存储主要存储非机密数据,大的数据. ...
- iOS网络编程-iCloud键值数据存储编程实例
iCloud键值数据存储设计 iCloud键值数据存储编程实例,画面中有两个开关控件,左图是设备1点击"设置iCloud数据"按钮,将控件状态保存到iCloud服务器.右图是设备2 ...
最新文章
- SpringBoot + Redis:模拟 10w 人的秒杀抢单!
- C++中getline()函数
- 通过命令行方式批量设置保留IP地址的代码
- linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化
- 语音识别中强制对齐_语音识别中的标注问题和嵌入式训练
- 【Java多线程编程】选号程序
- 怎么避免后台被搜索_复星保德信人寿保险有限公司星满意重大疾病保险怎么样?好不好?可信/靠谱吗?有什么优缺点/注意事项?值不值得买?一年多少钱?...
- winfrom实现简单计算器V2版本
- js获取cookie获取不到问题 vue获取cookie以及获取不到问题
- C# Types Type Members
- GUI Design Studio 4 5 151 0原型设计工具的使用
- 雷军100亿押注IoT,小米借AI两翼齐飞
- magento 安装出错 完全解决方案
- WP8开发日志(3):MVC设计模式进阶——绑定多个数据集
- load data infile 补充
- LINUX的awk和sed的常用用法 正则表达式 grep egrep用法
- bandicam安装注册
- lack名词形式_lack是什么意思_lack的翻译_音标_读音_用法_例句_爱词霸在线词典
- 什么是高中物理?一篇长长长长文告诉你!
- 利用子集构造法实现NFA到DFA的转换
热门文章
- 一文看懂国内人工智能行业产业链全景(必收藏)
- 红米10a和12c哪个好 红米10a和红米12c区别
- 随心所欲b超工作站图像处理_第七讲随心所欲版医学影像工作站软件每周一题...
- 《苏菲的世界》读书笔记之一:自然派哲学家
- couldn‘t find “libijkffmpeg.so“
- linux 内核 mtd读取,linux内核 mtd分区
- AURIX TriCore学习笔记四:LwIP裸机移植
- Tableau-热力图
- MFC架构之CWnd类
- ubuntu怎么连网线上网_安装完ubuntu 16.04连接网线无法上网解决