对于新手来说,iOS中使用的数据库框架,fmdb无疑是较为简单方便的。在我接触fmdb前,查阅了很多资料,发现网上的demo参差不齐,有些过于基础,项目中使用需要进一步封装。因此,我针对项目中的时候,参考别人的demo,自己改进并写了个封装。希望对大家使用fmdb有帮助。如果有错误的地方,希望多多指正,谢谢。此篇文章紧对刚学习fmdb的新人提供参考,大神请忽略。iOS开发群143898492,欢迎有兴趣的加入。
FMDB封装的工具
这是封装的工具类JHFMDBManager.h文件
#import <Foundation/Foundation.h>
#import"FMDB.h"
typedefvoid(^JHDBBlock)(FMDatabase*jh_db);
@interfaceJHFMDBManager :NSObject
+(instancetype)sharedInstance;
/**
*数据库操作
*
*@param block操作block回调
*/
- (void)SQLHandler:(JHDBBlock)block;
@end
这是JHFMDBManager.m文件,FMDatabaseQueue是多线程安全的,这个使用时需要注意,多线程操作数据时,必须保证FMDatabaseQueue是同一个对象,否则会导致数据正在被操作时被锁住的情况,导致操作失败。这里用了懒加载,只new一个对象。(由于排版的原因导致下面的代码分割开了,下面的代码应是连在一块的)。一般项目中只生成一个数据库,数据库里面多张表,保存不同对象数据。这里封装的- (void)SQLHandler:(JHDBBlock)block方法,是调用sql语句的block。如何使用请看下文。
#import"JHFMDBManager.h"
@interfaceJHFMDBManager()
@property(nonatomic,strong)FMDatabaseQueue* queue;
@end
@implementationJHFMDBManager
+ (instancetype)sharedInstance
{
static JHFMDBManager*sharedInstance =nil;
static dispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [selfnew];
});
returnsharedInstance;
}
//获取路径
+ (NSString*)dbPathWithDirectoryName:(NSString*)directoryName DataBaseName:(NSString*)dbname
{
NSString*docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject];
NSFileManager*filemanage = [NSFileManagerdefaultManager];
if(directoryName ==nil|| directoryName.length==0) {
docsPath = [docsPath stringByAppendingPathComponent:@"jhOnesmile"];
}else{
docsPath = [docsPath stringByAppendingPathComponent:directoryName];
}
BOOLisDir;
BOOLexit =[filemanage fileExistsAtPath:docsPathisDirectory:&isDir];
if(!exit || !isDir) {
[filemanage createDirectoryAtPath:docsPathwithIntermediateDirectories:YESattributes:nilerror:nil];
}
NSString*dbpath = [docsPathstringByAppendingPathComponent:dbname];
NSLog(@"---------%@", dbpath);
returndbpath;
}
- (void)SQLHandler:(JHDBBlock)block
{
//线程安全,可以用多线程操作
[self.queue inDatabase:^(FMDatabase*db) {
if([db open]) {
@try{
//成功回调
block(db);
}
@catch(NSException *exception) {
//处理异常,也可以直接抛出,这样调用者就能捕获到异常信息
NSLog(@"处理异常,异常信息: %@", exception);
}
@finally{
[dbclose];//如果[db open]就要保证能关闭
}
}else{
NSLog(@"数据库打开失败,错误提示:%@", [db lastError]);
}
db =nil;
}];
}
/**
*创建数据库多线程管理工具,必须是一个对象,否则会导致多线程使用中,出现操作失败的现象
*(两个操作同时操作一个数据库会出现程序锁,导致操作失败)
*
*@return
*/
-(FMDatabaseQueue*)queue{
if(_queue==nil) {
//只创建一个数据库,文件夹叫onesmile,数据库文件名字onesmile.sqlite,表名称根据创建的表来确定
NSString*dbName =@"onesmile.sqlite";
NSString*fileName =@"onesmile";
NSString*dbPath = [[self class]dbPathWithDirectoryName:fileNameDataBaseName:dbName];
_queue= [FMDatabaseQueue databaseQueueWithPath:dbPath];
}
return_queue;
}
自定义FMDB工具类的使用
我们有一个学生类,类属性如下。那么我们该如何将这个类的对象保存到数据库中呢?对于很多新手来说,希望省事点,能直接将对象保存到数据库,然而这是无法做到的。比如某个班级,有60个学生,我们应先建立一个学生表,表里面的列便是学生类的属性(正如项目中需要保存很多条新闻数据,或者是聊天数据等,那么新闻是一个模型,很多条新闻便是很多个对象,模型的属性我们便可以保存为新闻表的列)(这里有点啰嗦,只是解释给新手看的,高手略过)。
@interfaceJHUserModel :NSObject
/**用户名*/
@property(nonatomic,copy)NSString*name;
/**用户地*/
@property(nonatomic,copy)NSString*address;
/**用户年龄*/
@property(nonatomic,copy)NSString*age;
@end
1.创建学生类表
我们在需要保存数据的控制器里,先创建该学生类student的表。createSqlStr是保存sql语句,这里的sql语句的意思很明显,如果没有student这个表,则创建,并且列为id,name,address,age,id是主键,其他列都保存为text类型,且不为空(如果可以为空对应的列则not null去掉即可)。关于更深层次的sql语句的学习,推荐去w3c官网学习,毕竟不会sql语句,用起fmdb会感到很吃力。创建代码如下:
//创建表
[[JHFMDBManager sharedInstance]SQLHandler:^(FMDatabase*jh_db) {
NSString*createSqlStr =@"create table if not exists student (id integer primary key, name text not null,address text not null,age text not null)";
BOOL res = [jh_db executeUpdate:createSqlStr];
if(!res) {
NSLog(@"创建表出错");
}else{
NSLog(@"创建表成功");
}
}];
2.查询表
这里的set是查询返回的FMResultSet对象,使用while循环遍历所有查询到的结果,在遍历内获取你想要的列即可。实际应用中,有可能需要排序,翻页查询,某个列的查询最大最小值的那条数据等等,这就涉及到sql语句的应用了,具体可查询相关资料,只要写出该sql语句即可用如下的方式运行
//查询数据
[[JHFMDBManager sharedInstance]SQLHandler:^(FMDatabase*jh_db) {
NSString*sqlString =@"select *from student";
FMResultSet*set = [jh_db executeQuery:sqlString];
while([set next]) {
NSString*name = [set stringForColumn:@"name"];
NSString*address = [set stringForColumn:@"address"];
NSString*age = [set stringForColumn:@"age"];
NSLog(@"用户姓名:%@,地址:%@,年龄:%@",name,address,age);
}
}];
3.插入数据
//插入数据
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"insert into student (name,address,age) values(?,?,?)";
BOOL res = [jh_db executeUpdate:sqlString,student.name,student.address,[NSString stringWithFormat:@"%d",16]];
if(!res) {
NSLog(@"插入出错");
}else{
NSLog(@"插入成功");
}
}];
4.更新数据
某条数据变动了,则使用更新方法。
//更新数据
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"update student set address = ? where age = ?";
BOOLres = [jh_db executeUpdate:sqlString,@"gfds",student.age];
if(!res) {
NSLog(@"更新出错");
}else{
NSLog(@"更新成功");
}
}];
5.删除数据
删除数据需谨慎使用,一定要添加条件进行删除,否则容易闹出将整表甚至整个数据库删除的乌龙,需谨慎使用!
//删除数据
[[JHFMDBManager sharedInstance] SQLHandler:^(FMDatabase *jh_db) {
NSString *sqlString =@"delete from userModel where name = ?";
BOOLres = [jh_db executeUpdate:sqlString,userModel.name];
if(!res) {
NSLog(@"删除出错");
}else{
NSLog(@"删除成功");
}
}];
以上所有的操作都可以在子线程中执行,因为使用了FMDatabaseQueue,所以是线程安全的。很多不会用数据库的新人,都是对sql语句不熟悉导致的。因此建议使用fmdb的时候,电脑装个数据库查看软件,可以查看你对数据库进行的操作,否则你进行了数据操作,根本不知道数据库在背后到底如何做了什么。新人推荐使用SQLite Professional,想更深去学习sql,可以装个mysql环境,Mysql是免费的,可以使用它自带的MYSQLWorkbench管理工具查看数据库的操作。对于大神来说略过。
我是iOS菜鸟onesmile 一笑,刚开始写简书,希望各位多多指教。欢迎到iOS开发群143898492交流,群较小,但探讨问题较活跃。只要有问题都可以在里面,提问。懂的都会尽力解答。