课堂分享之FMDB

  • The only limit is your imagination. 唯一的受制是您的想象力。
本身是新手,一个不折不扣的新手,永远在追逐外人,此次出写,就是汇总下班上的早晨分享,和大神们的博客,有题目期待我们说出来,一起商量,致谢!

FMDB同时包容ARC和非ARC工程,会自行根据工程安插来调整有关的内存管理代码。

FMDB有七个关键的类
1.FMDatabase – 表示一个单身的SQLite数据库。 用来实施SQLite的授命。
2.FMResultSet –
表示FMDatabase执行查询后结果集,这些和Android的Cursor类似。
3.FMDatabaseQueue –
借使您想在多线程中执行四个查询或更新,你应当利用该类。那是线程安全的。

数据库创设
成立FMDatabase对象时参数为SQLite数据库文件路径。该路线可以是以下二种之一:
1..文书路径。该公文路径无需真实存,如若不存在会自动创设。
sqlite,2..空字符串(@””)。表示会在临时目录创建一个空的数据库,当FMDatabase
链接关闭时,文件也被删去。
3.NULL.
将创造一个内在数据库。同样的,当FMDatabase连接关闭时,数据会被灭绝。


一贯上手例子,边走边说:
本次分享先前时期准备了一个model

Person.h 文件中

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> @interface Person : NSObject @property(nonatomic, copy)NSString *name; @property(nonatomic, copy)NSString * gender; @property(nonatomic)NSInteger age,ID;//基本数据类型可以省略内存修饰符assign,因为默认使用的就是assign @property(nonatomic,strong)UIImage *photo; //自定义初始化方法 -(id)initWithName : (NSString *)name gender : (NSString *)gender age : (NSInteger)age photo : (UIImage *)photo; @end

Person.m文件

#import "Person.h" @implementation Person//自定义初始化方法 -(id)initWithName : (NSString *)name gender : (NSString *)gender age : (NSInteger)age photo : (UIImage *)photo{ if (self = [super init]) { self.name = name; self.gender = gender; self.age = age; self.photo = photo; } return self; } @end

开辟数据库

在和数据库交互
以前,数据库必须是开辟的。若是资源或权限不足不可以开拓或创办数据库,都会造成打开败北。

`-(void)viewDidLoad {
[super viewDidLoad];
// 获取Documents文件夹路径
NSString *urlString =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,
YES) lastObject];
// 在Documents文件夹里创制数据库文件 db.sqlite
NSString *dbPath = [urlString
stringByAppendingPathComponent:@”db.sqlite”];
// 创立数据库对象
// 参数:数据库的门径

    // 执行结束后并没有帮我们生成数据库文件,只是帮我们创建了数据库对象    
 FMDatabase *db = [FMDatabase databaseWithPath:dbPath];     
 NSLog(@"%@",NSHomeDirectory());    
   // 代开数据库    
   // open操作才帮我们真正的创建数据库文件,且如果已经打开,直接返回YES,此时可以直接使用,如果打开失败会打印报错信息    
  BOOL isOpen = [db open];    
  if (isOpen) {        
       NSLog(@"打开成功");        
       //创建表格        
       //executeUpdate 除了查询之外,其他数据创建表格,插入数据、删除数据都是用这个方法       
      // blob 二进制流 相当于oc的NSData        
      BOOL isCreat =   [db executeUpdate:@"create table if not exists Person(id integer primary key autoincrement,name text,gender text,age integer,photo blob)"];        
      NSLog(@"%@",isCreat ? @"建表成功":@"建表失败");           
   }else{       
    NSLog(@"打开失败");    
   }    
 //给属性赋值
  self.db = db;
  NSLog(@"%@",NSHomeDirectory());
       // 可以根据打印的地址,自行查看

}`

履行更新
万事不是SELECT命令的吩咐都实属更新。那包含 CREATE, UPDATE,
INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM,
and REPLACE (等)。
概括的话,只要不是以SELECT初步的授命都是UPDATE命令。

进行更新重返一个BOOL值。YES代表执行成功,否则表示有这个错误 。你可以调用
-lastErrorMessage 和 -lastErrorCode方法来赢得越来越多信息。

// 插入
- (IBAction)insertButtonAction:(id)sender { Person *p = [[Person alloc]initWithName:@"美美" gender:@"女" age:20 photo:[UIImage imageNamed:@"3.gif"]]; //将图片转化成NSData对象 NSData *data = UIImagePNGRepresentation(p.photo); //@(p.age)参数必须是对象类型的才能使用 //插入操作 BOOL isInsert = [self.db executeUpdate:@"insert into Person(name,gender,age,photo)values(?,?,?,?)",p.name,p.gender,@(p.age),data]; NSLog(@"%@",isInsert ? @"插入成功":@"插入失败"); if (isInsert == YES) { NSLog(@"插入成功"); }else{ NSLog(@"插入失败"); } }


// 删除
- (IBAction)deleteButtonAction:(id)sender { //根据条件删除 BOOL result = [self.db executeUpdate:@"delete from Person where id = ?",@1]; if (result == YES) { NSLog(@"删除成功"); }else{ NSLog(@"删除失败"); } //删除全部表格内容 // id 不会清空 // BOOL isResult1 = [self.db executeUpdate:@"delete from Person"]; // 删除表格 // id 清空 // BOOL isResult2 = [self.db executeUpdate:@"drop table Person"]; }


// 更新
`- (IBAction)updataButtonActton:(id)sender {

    BOOL isUpdate = [self.db executeUpdate:@"update Person set gender = ? where id = ?",@"男",@4];    
    if (isUpdate == YES) {        
          NSLog(@"更新成功");    
    }else{        
          NSLog(@"更新入失败");    
   }   

}`

实施查询

SELECT命令就是询问,执行查询的法子是以 -excuteQuery发轫的。

施行查询时,若是成功重回FMResultSet对象, 错误重临nil.
与履行更新万分,支持选拔 NSError**参数。同时,你也可以使用
-lastErrorCode和-lastErrorMessage获知错误音讯。

// 查询
- (IBAction)selectButtonActton:(id)sender { // 查询全部 FMResultSet *set = [self.db executeQuery:@"select * from Person"]; // 按条件查询 // FMResultSet *set = [self.db executeQuery:@"select *from Person where name = ?",@"美美"]; self.dataArray = [NSMutableArray arrayWithCapacity:0]; // 循环取出表中的数据 // [set next] 判断写一行是否有数据 // [set next]可以轮询query回来的资料,每一次的next可以得到一个row里对应的数值,并用[rs stringForColumn:]或[rs intForColumn:]等方法把值转成Object-C的型态。 // if [FMResultSet next] 查询某一条信息 while ([set next]) { //取出每一个字段对应的数据 NSInteger ID = [set intForColumn:@"id"]; //取出id字段下的数据 NSString *name = [set stringForColumn:@"name"];//取出name字段下的数据 NSString *gender = [set stringForColumn:@"gender"];//取出gender字段下的数据 NSInteger age = [set intForColumn:@"age"];//取出age字段下的数据 NSData *data = [set dataForColumn:@"photo"];//取出photo字段下的数据 //创建model类 //将二进制流转成图片 UIImage *image = [UIImage imageWithData:data]; Person *p = [[Person alloc]initWithName:name gender:gender age:age photo: image]; p.ID = ID; // 保存你需要的信息 [self.dataArray addObject:p]; } }

FMResultSet 提供了很多措施来博取所需的格式的值:
intForColumn:
longForColumn:
longLongIntForColumn:
boolForColumn:
doubleForColumn:
stringForColumn:
dataForColumn:
dataNoCopyForColumn:
UTF8StringForColumnIndex:
objectForColumn:

这个办法也都不外乎 {type}ForColumnIndex
的那规范的法门,参数是查询结果集的列的目录地点。
你无需调用 [FMResultSet close]来关闭结果集,
当新的结果集暴发,或者其数据库关闭时,会自行关闭。

关门数据库
当使用完数据库,你应当 -close 来关闭数据库连接来刑满释放SQLite使用的资源。

[db close]; 

事务

FMDatabase是支撑工作的。

数据净化(数据格式化)

利用FMDB,插入数据前,你不用花时间审查你的数码。你可以运用规范的SQLite数据绑定语法。
INSERT INTO myTable VALUES (?, ?, ?)
SQLite会识别 “?” 为一个输入的点位符,
那样的进行会接受一个可变参数(或者表示为其它参数,如NSArray,
NSDictionary,或va_list等),会不错为你转义。

您也得以接纳使用命名参数语法。

 INSERT INTO myTable VALUES (:id, :name, :value)   

参数名必须以冒名初阶。SQLite本身帮忙其余字符,当Dictionary
key的其中贯彻是冒号起首。注意你的NSDictionary key不要包涵冒号。

NSDictionary *argsDict = [NSDictionary dictionaryWithObjectsAndKeys:@"My Name", @"name", nil];  
 [db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];   

并且,代码不能够这么写(为何?想想呢。)

      [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has \\" lots of ' bizarre \\" quotes '"]; 

你应该:

     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @"this has " lots of ' bizarre " quotes '"];   

提需求 -executeUpdate:
方法的参数都不可能不是目标。如同以下的代码就无法工作,且会生出崩溃。

     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];   

毋庸置疑有做法是把数字打包成 NSNumber对象

[db executeUpdate:@”INSERT INTO myTable VALUES (?)”, [NSNumber
numberWithInt:42]];

要么,你可以运用 -execute*WithFormat: ,那是NSString风格的参数

    [db executeUpdateWithFormat:@"INSERT INTO myTable VALUES (%d)", 42]; 

-execute*WithFormat: 的方式的内部贯彻会帮你封装数据,
以下那些修饰符都可以行使: %@, %c, %s, %d, %D,%i, %u, %U, %hi, %hu, %qi,
%qu, %f, %g, %ld, %lu, %lld, and %llu.
除此之外的修饰符可能引致力不从心预见的结果。
一些景况下,你须求在SQL语句中利用 % 字符,你应该选取 %%。

线程安全
比方我们的 app 须要二十四线程操作数据库,那么就须求选取 FMDatabaseQueue
来担保线程安全了。 切记不能够在多个线程中一块一个 FMDatabase
对象并且在多个线程中还要利用,那一个类本身不是线程安全的,那样使用会造成数据错乱等题材。

运用 FMDatabaseQueue 很粗略,首先用一个数据库文件地方来初使化
FMDatabaseQueue,然后就足以将一个闭包 (block) 传入 inDatabase 方法中。
在闭包中操作数据库,而不直接参加 FMDatabase 的军事管制。

// 创设,最好放在一个单例的类中

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; // 使用[queue inDatabase:^(FMDatabase *db) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; FMResultSet *rs = [db executeQuery:@"select * from foo"]; while ([rs next]) { // … } }]; // 如果要支持事务 [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; if (whoopsSomethingWrongHappened) { *rollback = YES; return; } // etc… [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; }];

正文后期的事体和多线程没有何样想法就什么样也不曾增加。
本作品一大半都是人家的,我是为着做个笔记,也多少个东西给大家参考下
转自:
唐巧一级大神引用
FMDB官方使用文档-GCD的运用-进步性能(翻译)

网站地图xml地图