iOS FMDB小结
来源:互联网 发布:owncloud php 编辑:程序博客网 时间:2024/06/05 22:44
作为iOS传统的数据库封装工具库FMDB,大家都很熟悉,原来也用过,主要没有系统的总结,这次总结一下吧,其实是看了好几篇别人的日志然后自己再加工了一下。
首先是库的导入有两种选择
1 从gitHub上下载 https://github.com/ccgus/fmdb 然后导入系统库 libSqlite3.tbd
2 pod上面下载 pod 'FMDB'
然后是使用
数据库最基本的操作就是大家所知道的增删改查
1 数据库作为整个项目中都可能使用的本地存储方案,可以用一个单例来创建全局共享
+ (DataBaseManager *)sharedDatabaseManager{ static DataBaseManager *manager = nil; @synchronized(self){ if (manager == nil) { manager = [[self alloc] init]; } } return manager;}
2 因为数据库要保存在本地,一定要有路径
-(NSString *)getDBPath{ NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSFileManager *filemanage = [NSFileManager defaultManager]; docsdir = [docsdir stringByAppendingPathComponent:@"FMDBDemo"]; BOOL isDir; BOOL exit =[filemanage fileExistsAtPath:docsdir isDirectory:&isDir]; if (!exit || !isDir) { [filemanage createDirectoryAtPath:docsdir withIntermediateDirectories:YES attributes:nil error:nil]; } NSString *dbpath = [docsdir stringByAppendingPathComponent:@"work.sqlite"]; return dbpath;}
3 准备工作都做好了,然后就是创建数据库了
//先获取work.sqlite在沙盒中的路径 NSString *fileName = [self getDBPath]; //创建数据库对象 _database = [[FMDatabase alloc] initWithPath:fileName]; NSLog(@"databasePath:%@",_database.databasePath);4 然后是创建表,如果是第一次就是创建,第二次就是访问数据表了,所以需要一个简单的判断,当前表是否已经存在
// 判断是否存在表- (BOOL)isTableOK:(NSString *)tableName{ FMResultSet *rs = [_database executeQuery:@"select count(*) as 'count' from sqlite_master where type ='table' and name = ?", tableName]; while ([rs next]){ // just print out what we've got in a number of formats. NSInteger count = [rs intForColumn:@"count"]; NSLog(@"isTableOK %ld", count); if (0 == count) { return NO; } else { return YES; } } return NO;}5 如果不存在就创建表
-(void)createTable{ NSString *sql = @"CREATE TABLE IF NOT EXISTS workTable" @"(serial integer PRIMARY KEY AUTOINCREMENT," @"workId Varchar(1024)," @"age integer NOT NULL," @"name Varchar(1024));"; BOOL isSuccess = [_database executeUpdate:sql]; if (!isSuccess) { NSLog(@"%@",[_database lastErrorMessage]); }else{ NSLog(@"创建数据表成功"); }}
- (id)init{ if (self = [super init]) { //先获取work.sqlite在沙盒中的路径 NSString *fileName = [self getDBPath]; //创建数据库对象 _database = [[FMDatabase alloc] initWithPath:fileName]; NSLog(@"databasePath:%@",_database.databasePath); //打开数据库 if ([_database open]) {//第一次打开如果没有那么就创建并打开 如果有直接打开 //打开成功 //如果没有表就创建表 if (![self isTableOK:@"workTable"]) { [self createTable]; }else{ NSLog(@"表已经存在"); } }else{ NSLog(@"open database:%@",[_database lastErrorMessage]); } } return self;}6 表创建好了,还需要一个对象
.h
#import <Foundation/Foundation.h>@interface Worker : NSObject@property (nonatomic,copy) NSString *workId;@property (nonatomic,copy) NSString *name;@property (nonatomic,assign) NSInteger age;@end
7 数据库的操作了
1 增加
其中需要注意的是,加入int类型的数据格式,需要用@()
-(void)insertDataFromModel:(Worker *)model{ if ([self isExistDataFromId:model.workId]) { return; }else{ NSString *sql = @"insert into workTable (workId,age,name) values(?,?,?)"; BOOL isSuccess = [_database executeUpdate:sql,model.workId,@(model.age),model.name]; if (!isSuccess) { NSLog(@"insert error:%@",[_database lastErrorMessage]); }else{ NSLog(@"插入成功"); } }}
-(BOOL)isExistDataFromId:(NSString *)workId{ NSString *sql = @"select * from workTable where workId = ?"; FMResultSet *rs = [_database executeQuery:sql,workId]; if([rs next]){ return YES; }else{ return NO; }}
2 删除
-(void)deleteFronWorkId:(NSString *)workId{ NSString *sql = @"delete from workTable where workId = ?"; BOOL isSuccess = [_database executeUpdate:sql,workId]; if (!isSuccess) { NSLog(@"delete Error:%@",[_database lastErrorMessage]); }else{ NSLog(@"删除成功"); }}3 修改
-(void)updateSetName:(NSString *)name age:(NSInteger)age WhereworId:(NSString *)workId{ NSString *sql = @"update workTable set name = ?,age = ? where workId = ?"; BOOL isSuccess = [_database executeUpdate:sql,name,@(age),workId]; if (!isSuccess) { NSLog(@"update Error:%@",[_database lastErrorMessage]); }else{ NSLog(@"更新成功"); }}4 查询
-(NSMutableArray *)getAllData{ NSString *sql = @"select * from workTable"; FMResultSet *rs = [_database executeQuery:sql]; NSMutableArray *arr = [[NSMutableArray alloc] init]; while ([rs next]) { Worker *model = [[Worker alloc] init]; model.workId = [rs stringForColumn:@"workId"]; model.name = [rs stringForColumn:@"name"]; model.age = [rs intForColumn:@"age"]; [arr addObject:model]; } return arr;}8 多线程的操作
1 因为FMDB是非线程安全,所以需要同步处理数据,FMDB就用了inDataBase和inTransaction这两个函数
2 还有一个问题是主线程访问数据库的时候,后台正在刷新或者添加数据,需要等待,可以把inDataBase和inTransaction放在异步里面
等更新完了再刷新UI,就跟图片下载再加载的道理是一样的。
首先要导入FMDataBaseQueue.h
inDataBase例子
-(void)testDataBaseQueueFrom:(NSMutableArray *)arr{ //1.创建队列 FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self getDBPath]]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [queue inDatabase:^(FMDatabase *db) { TICK; for (Worker *model in arr) { NSString *sql = @"insert into workTable (workId,age,name) values(?,?,?)"; BOOL isSuccess = [db executeUpdate:sql,model.workId,@(model.age),model.name]; if (!isSuccess) { NSLog(@"insert error:%@",[_database lastErrorMessage]); }else{ NSLog(@"插入成功"); } } TOCK; }]; //主队列获取数据 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"finish"); for (Worker *model in [self getAllData]) { NSLog(@"workId:%@ name:%@ age:%li",model.workId,model.name,(long)model.age); } }); });}inTransaction例子
-(void)testDataTransactionFrom:(NSMutableArray *)arr{ //1.创建队列 FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self getDBPath]]; //2.把任务包装到事务里 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [queue inTransaction:^(FMDatabase *db, BOOL *rollback){ TICK; for (Worker *model in arr) { NSString *sql = @"insert into workTable (workId,age,name) values(?,?,?)"; BOOL isSuccess = [db executeUpdate:sql,model.workId,@(model.age),model.name]; if (!isSuccess) {//如果有错误 返回 NSLog(@"insert error:%@",[_database lastErrorMessage]); *rollback = YES; return; }else{ NSLog(@"插入成功"); } } TOCK; }]; //主队列获取数据 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"finish"); for (Worker *model in [self getAllData]) { NSLog(@"workId:%@ name:%@ age:%li",model.workId,model.name,(long)model.age); } }); });}两者运行的目的都是一样的,但是运行的效率差别还是比较大的,因为后者用了数据库的事务处理,在插入5000条数据的时候,都是模拟器运行的条件下
前者需要14秒,后者需要1秒
其中的时间运算宏定义
#define TICK NSDate *startTime = [NSDate date]#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])
Demo
http://download.csdn.net/detail/rpf2014/9679162
参考文档
http://blog.csdn.net/zhangao0086/article/details/44223007 0 0
- iOS FMDB小结
- iOS FMDB的一些基本操作小结
- iOS FMDB
- iOS FMDB
- iOS-FMDB
- iOS FMDB
- iOS FMDB
- iOS-FMDB
- fmdb使用小结
- FMDB初步使用小结
- IOS开发~FMDB备忘
- [iOS]FMDB入门学习
- iOS FMDB Sqlite
- IOS开发 FMDB
- IOS开发~FMDB备忘
- FMDB iOS
- iOS FMDB的使用
- ios FMDB 存储数据
- 树--->二叉树
- JAVA设计模式之(一)接口模式
- spring +ajax 交互传值遇到的问题
- node.js学习笔记_模拟路由
- 仿网易轮播图
- iOS FMDB小结
- 模块的规范方式
- Javascript基础_11作用域与块级作用域
- VR系列——Oculus Audio sdk文档:一、虚拟现实音频技术简介(7)——虚拟现实的混合场景
- HDU 2476 String painter(区间dp)
- MATLAB中的impixel函数——获取图像像素值
- 2016年11月8日晚21时16分,首次使用博客,仅记
- React
- Linux TCP协议使用线程实现并发服务器