iOS学习笔记,数据库之FMDB简单介绍
分类:计算机编程

此时此刻,尽管SQLite也为iOS提供了数据库操作方法,但越多的时候,一般用FMDB,正如主流应用软件会用到。这里介绍三个询问主流应用程式首要框架的网址:AppSight 。

FMDB v2.6.2

体系中央银行使 ARC 依旧 MRC,对利用 FMDB 都不曾其他影响,FMDB 会在编写翻译项目时自动相称。

iOS 中原生的 SQLite API 在采取上一定不自身,在行使时,特别困难。于是,就出现了一各个将SQLite API举行打包的库,比如FMDB、PlausibleDatabase、sqlitepersistentobjects等,FMDB 是一款轻巧、易用的封装库,这一篇小说简介下FMDB的选取。coreData 与 FMDB 的界别:coreData:自动生成 SQL 语句,无法和煦设置,性子化的、优化的等 SQL 语句不可能促成;FMDB:能够本人定制差别的 SQL 语句,扩张性好;

  • 那篇小说,主要选取FMDB官方文书档案中的行使情势一些开展了翻译。关于Pod以及Carthage安装第三方库的有些,可以参照他事他说加以考察小编相关文章(Pod,Carthage)。FMDB官方源码地址传送门: 。

  • FMDB是SQLite的Objective-C包装器: 。由于FMDB是创立在SQLite之上的,所以您至少阅读有关页面贰次: 。

  • 只看官方文书档案是非常不够的,看完后要多融合介绍的那么些主意开展练习。关于FMDB的利用示例代码和DEMO能够参照他事他说加以考察小编的另一篇小说 。

这是个SQLite的OC封装。SQLite的地址:

一、类使用

  1. FMDatabase: 代表单个数据库,用它来推行SQL语句。
  2. FMResultSet: 代表数据库的查询。
  3. FMDatabaseQueue:若是数据库在三十二线程要拓宽询问和换代,就选取FMDatabaseQueue这几个类,

一、在类型中增加FMDB库,具体参见 使用手动导入或 pod

图片 1

FMDB邮件名单

二、数据库的开创

FMDatabase类能够因而数据库路径来创建数据库,如下有二种办法获得数码路线
1、系统路径: 在磁盘上从未有过公文,借使上磁盘上尚未数据库文件,FMDatabase会为大家创立。
2、空的字符串:要是数据库的门道是空字符串时,数据库将放在沙盒中temporary,若是数据库未有连接时,数据库将会被删去。
3、NULL的数据库路线:假若数据库路线是NULL,数据库会被创制,不过数据库没有连接时,数据库将会被删除。

NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];
FMDatabase *db = [FMDatabase databaseWithPath:path];

二、在FMDB中有四个重要的类:FMDatabase - 代表一个 SQLite 数据库。用于执行SQL 语句。FMResultSet - 代表 FMDatabase 实行四个查询的结果。FMDatabaseQueue - 要是您想在八个线程施行查询和立异,你会想要使用那个类。那是“线程安全”一节中陈诉。

FMDB有多个根本的类:

三、打开数据库

在采用数据库在此之前,必需求开发数据库,果未有丰富的能源和权力来张开创建数据库,数据库会展开失败。

//当数据打开失败时,作为处理
if (![db open]) 
{
    db = nil;
    return;
}

三、数据库创建只要满意以下三条中的放肆一条,二个 FMDatabase 就创制一个SQLite 数据库文件路线:1)当数据库文件不设有的时候,fmdb 会本人创设三个。2)如若你传入的参数是一穷二白:@"" ,则 fmdb 会在一时文件目录下开创这些数据库,数据库断开连接时,数据库文件被删除。3)借使您传入的参数是 NULL,则它会树立三个在内部存款和储蓄器中的数据库,数据库断开连接时,数据库文件被删去。

  • FMDatabase:表示贰个独门的SQLite数据库。 用来进行SQLite的命令。
  • FMResultSet:表示FMDatabase实践查询后结果集
  • FMDatabaseQueue:要是你想在八线程中实行多个查询或更新,你应有使用该类。那是线程安全的。

读书SQLite的广阔难题

三、数据库更新

除开SELECT语句外,全体的SQL语句都是翻新,更新满含CREATE, UPDATE, INSERT, ALTE奇骏, COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, and REPLACE 注脚(以至越来越多)。若是SQL语句未有SELECT ,那么该SQL语句是立异。试行更新SQL语句时,会回来单个数值如BOOL。
实践更新语句后会重临一个 BOOL 值,重返 YES 表示推行更新语句成功,再次来到 NO 表示出现错误,能够经过调用 -lastErrorMessage 和 -lastErrorCode 方法获得更加的多错误音讯。
关于SQL语句的施用,一、数据库之SQL语句;

图片 21.jpg

1.1 数据库创建(Database Creation)

创设FMDatabase对象时参数为SQLite数据库文件路线。该路线可以是以下二种之一:

  • 1.文书路线。该文件路线无需真实存,假如不设有会自动创制。
  • 2.空字符串。表示会在一时目录创设贰个空的数据库,当FMDatabase 链接关闭时,文件也被删去。
  • 3.NULL. 将开创三个内在数据库。同样的,当FMDatabase连接关闭时,数据会被灭绝。
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];FMDatabase *db = [FMDatabase databaseWithPath:path];

(如需对一时数据库或内在数据库进行一步了然,请继续读书:)

四、数据库查询

用-executeQuery...格局来查询数据库内容。假诺查询数据成功会回去FMResultSet,不然重返是一个空。-lastErrorMessage 和 -lastErrorCode方法寻找未果原因。
为了得到数据库查询的结果,使用while循环,在FMDB中得以轻易的实现。

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
    //retrieve values for each record
}

就算只供给获得叁个数额,也仍然必得在探问问调查询结果前调用 -[FMResultSet next]。

FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];
if ([s next]) {
    int totalCount = [s intForColumnIndex:0];
}

FMResultSet有如下方法取得每列中的相应的数额

  • intForColumn:
  • longForColumn:
  • longLongIntForColumn:
  • boolForColumn:
  • doubleForColumn:
  • stringForColumn:
  • dateForColumn:
  • dataForColumn:
  • dataNoCopyForColumn:
  • UTF8StringForColumnName:
  • objectForColumnName:
    那些办法都有三个 {type}ForColumnIndex: 变体,是基于列的职责来询问数据。

普普通通状态下,多少个 FMResultSet 不须求手动 -close,因为结果会集 (result set) 被保释恐怕源数据库关闭会自动关闭。
五、关闭数据库
当成功数据库的查询和革新时,须求调用 -close方法去关闭数据库。

[db close];

四、展开数据库

1.2 展开数据库

在和数据库交互此前,数据库必须是开荒的。假诺财富或权限不足无法伸开或创制数据库,都会促成展开战败。

if (![db open]) { [db release]; //ARC无需此行 return; } 

是因为FMDB创立在SQLite之上,你想要至上而下读一回这几个页面。当您在此间,确认保障您标志了SQLite的文书档案页面:

六、事务

由此合理的办法只怕试行 begin/end transaction语句,FMDatabase能够初阶和付出业务。

图片 3

1.3 推行更新(Executing Updates)

整整不是SELECT命令的命令都说是更新。这包括CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, and REPLACE

简言之的话,只要不是以SELECT起来的命令都以UPDATE命令。

推行更新再次来到多个BOOL值。YES意味着施行成功,不然表示有那一个错误 。你能够调用-lastErrorMessage-lastErrorCode办法来猎取更加多新闻。

施行更新的法门是以-executeUpdate:开头的。

特约Contributing

七、数据库批量讲话和操作

能够用FMDatabase 的executeStatements:withResul-tBlock: 方法中施行几个字符串语句。

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
                 "create table bulktest2 (id integer primary key autoincrement, y text);"
                 "create table bulktest3 (id integer primary key autoincrement, z text);"
                 "insert into bulktest1 (x) values ('XXX');"
                 "insert into bulktest2 (y) values ('YYY');"
                 "insert into bulktest3 (z) values ('ZZZ');";

success = [db executeStatements:sql];

sql = @"select count(*) as count from bulktest1;"
       "select count(*) as count from bulktest2;"
       "select count(*) as count from bulktest3;";

success = [self.db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) {
    NSInteger count = [dictionary[@"count"] integerValue];
    XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary);
    return 0;
}];

八、数据的管理
给FMDB提供SQL语句时,推行语句前并不是品味管理任何值,应该参照如下的写法。

INSERT INTO myTable VALUES (?, ?, ?, ?)

?能够被SQLite识别,并将它作为三个占位符。FMDB 试行语句的情势都领受七个参数 (举个例子NSArray,NSDict-ionary,va_list),并将它们转义成精确数值。
在Objcetive-C中SQL用?作为占位符。

NSInteger identifier = 42;
NSString *name = @"Liam O'Flaherty ("the famous Irish author")";
NSDate *date = [NSDate date];
NSString *comment = nil;

BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", @(identifier), name, date, comment ?: [NSNull null]];
if (!success) {
    NSLog(@"error = %@", [db lastErrorMessage]);
}

Fundamental 类型的多寡,如identifier是整形,整形应该将转成NSNumber,如下边代码用@将整形转化成NSN-umber。或然用[NSNumber numberWithInt:identi-fier]办法将整形转化成NSNumber。
同一,SQL NULL 值应该是插入[NSNull null],如下边代码中comment可能为空,使用comment ?: [NSNull null]说话,即使comment 不为空时,将插入字符串,不可是插入[NSNull null];

如故,能够用利用如下语句

INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)

参数相对倘使有冒号。SQLite本人补助任何的标志,在字典的键前边有冒号,相对无法在字典前边用冒号

NSDictionary *arguments = @{@"identifier": @(identifier), @"name": name, @"date": date, @"comment": comment ?: [NSNull null]};
BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)" withParameterDictionary:arguments];
if (!success) {
    NSLog(@"error = %@", [db lastErrorMessage]);
}

五、关闭数据库

1.4 推行查询(Executing Queries)

SELECT一声令下正是查询,实施查询的主意是以-excuteQuery:开头的。

进行查询时,假诺成功重回FMResultSet对象,错误重返nil. 与实践更新分外,辅助使用 NSError**参数。同期,你也得以运用-lastErrorCode-lastErrorMessage获知错误消息。

为了遍历查询结果,你能够行使while循环。你还索要了然怎么跳到下贰个记下。使用FMDB,很轻松完成,如同那样:

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];while  { //retrieve values for each record}

在您拜谒问调查询重回值在此之前,你必需平素调用-[FMResultSet next] ,纵然你只想要二个记下:

FMResultSet *s = [db executeQuery:@"SELECT COUNT FROM myTable"];if  { int totalCount = [s intForColumnIndex:0];}

FMResultSet 提供了许多办法来博取所需的格式的值:

  • intForColumn:
  • longForColumn:
  • longLongIntForColumn:
  • boolForColumn:
  • doubleForColumn:
  • stringForColumn:
  • dataForColumn:
  • dataNoCopyForColumn:
  • UTF8StringForColumnIndex:
  • objectForColumn:

那么些点子也都不外乎 {type}ForColumnIndex的那样子的艺术,参数是查询结果集的列的目录地点。

你没有必要调用 [FMResultSet close]来关闭结果集, 当新的结果集发生,可能其数据库关闭时,会自动关闭。

至于FMBDB你是还是不是有怎么着奇怪的主旨呢?你应当怀想联系ccgus,然则你得规定他并未因为部分理由限定了那么些抢手。其他,pull是不管三七二十一的,保持你本地编制程序的习贯。可是,即便几个礼拜也未有收到来自ccgus的别样消息也别焦急,你能够发个音讯问一下生出了什么。

最注重一点是,SQL语句中并不是用NSString方法给拼接字符串,如stringWithFormat。

图片 4

1.5 关闭数据库

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

[db close]; 

CocoaPods

九、FMDatabaseQueue 和线程安全

FMDatabase 这么些类是线程不安全的,在三十二线程中应用 FMDatabase 单例是最为错误做法。不能够在三十六线程的情况中对数据库 FMDatabase 进行读写,会产出奔溃只怕分外,因为你不可能确定保证你读数据的同不常间另外一条线程不在写多少。由此无法在十六线程中使用FMDatabase 单例。
相反使用在多线程中效果FMDatabaseQueue。用FMDatabaseQueue单例和在多个线程中采纳它。FMDatabaseQueue单例是跨线程是同步的。如下是怎么使用它。

//创建自己的队列
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

//使用FMDatabaseQueue
[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @1];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @2];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @3];

    FMResultSet *rs = [db executeQuery:@"select * from foo"];
    while ([rs next]) {
        …
    }
}];

FMDatabaseQueue在业务中的使用

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @1];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @2];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @3];

    if (whoopsSomethingWrongHappened) {
        *rollback = YES;
        return;
    }
    // etc ...
}];

如上是翻译自法定文书档案,和参考FMDB 使用办法,当中Swift部分略去,请见谅;
出于岁月有限,不足之处,请指正,谢谢!

六、实践更新除了查询操作,FMDB数据库操作都施行 executeUpdate 方法,那一个办法重回 BOOL 型。

1.6 事务(Transactions)

FMDatabase是永葆工作的。

FMDB支持CocoaPods做注重管理。

图片 5

1.7 多种语句和批次消息(Multiple Statements and Batch Stuff)

你能够利用FMDatabaseexecuteStatements:withResultBlock:在字符串中施行多个语句:

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);" "create table bulktest2 (id integer primary key autoincrement, y text);" "create table bulktest3 (id integer primary key autoincrement, z text);" "insert into bulktest1  values ;" "insert into bulktest2  values ;" "insert into bulktest3  values ;";success = [db executeStatements:sql];sql = @"select count as count from bulktest1;" "select count as count from bulktest2;" "select count as count from bulktest3;";success = [self.db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) { NSInteger count = [dictionary[@"count"] integerValue]; XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary); return 0;}];

假若要求多少可加密你须要采纳FMDB/SQLCipher.FMDB/SQLCipher注脚了SQLCipher的注重,允许FMDB通过“-DSQLITE_HAS_CODEC”标识去编译。

以下是自己要作为表率遵从规则代码:

1.8 数据格式化(Data Sanitization)

运用三个SQL语句为FMDB插入数据前,你不用品味SQL核查任何值。相反的,你应有使用正式的SQLite数据绑定语法。

INSERT INTO myTable VALUES (?, ?, ?, ?) 

?字符由SQLite识别为要插入的值的占位符。这一个实行格局漫天收受多少可变的参数(或那一个参数的八个象征,比如NSArray,NSDictionaryva_list)。

并且,在Objective-C中校该SQL的占位符?一起利用:

NSInteger identifier = 42;NSString *name = @"Liam O'Flaherty ("the famous Irish author")";NSDate *date = [NSDate date];NSString *comment = nil;BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", @(identifier), name, date, comment ?: [NSNull null]];if  { NSLog(@"error = %@", [db lastErrorMessage]);}

注意:基本数据类型,如NSInteger变量identifier,应该是八个NSNumber对象,通过利用@如上所示的语法完毕。只怕你也能够运用[NSNumber numberWithInt:identifier]语法。

同样,NULL应该插入SQL 值[NSNull null]。比如,在案件的comment,那大概是nil(並且是在那些事例中),你能够应用comment ?: [NSNull null]语法,倘诺将插入字符串comment不是nil,而是将插入[NSNull null]一旦它是nil。

在斯威夫特中,您将采纳它executeUpdate,那不独有是三个精简的斯威夫特语法,而且也是throws错误管理准确的不当:

do { let identifier = 42 let name = "Liam O'Flaherty ("the famous Irish author")" let date = Date() let comment: String? = nil try db.executeUpdate("INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", values: [identifier, name, date, comment ?? NSNull} catch { print("error = }

注意:在斯维夫特中,您不用像Objective-C那样包装大旨的数字类型。不过只要要插入三个可选的字符串,你可能会利用comment ?? NSNull()语法(即,假使是nil,使用NSNull,不然使用字符串)。

抑或,您能够行职分名参数语法:

INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)

参数名必需以冒名初阶。SQLite本人援助别的字符,但Dictionary key的中间贯彻是冒号开首,所以注意你的NSDictionary key不要包蕴冒号。

NSDictionary *arguments = @{@"identifier": @(identifier), @"name": name, @"date": date, @"comment": comment ?: [NSNull null]};BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)" withParameterDictionary:arguments];if  { NSLog(@"error = %@", [db lastErrorMessage]);}

主若是不用采取NSString方法stringWithFormat手动将值插入SQL语句笔者。贰个斯威夫特字符串插入也不应当将值插入到SQL中。使用?占位符将值插入到数据库中(或WHERE在SELECT语句中的子句中运用)。

FMDB类参考

图片 6

1.9 补充:老版本的README

提供给-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 ", 42]; 

-execute*WithFormat: 的点子的内部贯彻会帮你封装数据, 以下那么些修饰符都能够行使: %@, %c, %s, %d, %D,%i, %u, %U, %hi, %hu, %qi, %qu, %f, %g, %ld, %lu, %lld, and %llu。 除外的修饰符恐怕导致无可奈何预见的结果。 一些意况下,你假使要在SQL语句中动用 % 字符,你应当运用%%

在七个线程中何况利用三个FMDatabase实例是不明智的。贰个线程一个FMDatabase对象平素是足以的。只是不要跨线程分享单个实例,相对不用同时跨多少个线程。不然,意外会平常产生,程序会时临时崩溃,或许报告足够。综上可得很崩溃。

进而,不要实例化单个FMDatabase对象,并在八个线程中选用。

而是利用FMDatabaseQueue。实例化多个FMDatabaseQueue,并跨多个线程使用它。该FMDatabaseQueue对象将联袂并和睦跨多少个线程的拜谒。以下是怎样选用它:

第一,令你的系列。

FMDatabaseQueue * queue = [FMDatabaseQueue databaseQueueWithPath: aPath];

接下来选择它像那样:

[queue inDatabase: ^(FMDatabase * db){ [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 1 ]; [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 2 ]; [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 3 ]; FMResultSet * rs = [db executeQuery:@“ select * from foo ” ]; while([rs next ]){ ... } }]

在transaction中封装职业的简要方法:

[queue inTransaction: ^(FMDatabase * db,BOOL * rollback){ [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 1 ]; [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 2 ]; [db executeUpdate:@“ INSERT INTO myTable VALUES”,@ 3 ]; if(whoopsSomethingWrongHappened){ * rollback = YES ; return ; } // etc ... }];

Swift相应的版本为:

queue.inTransaction { db, rollback in do { try db.executeUpdate("INSERT INTO myTable VALUES ", values: [1]) try db.executeUpdate("INSERT INTO myTable VALUES ", values: [2]) try db.executeUpdate("INSERT INTO myTable VALUES ", values: [3]) if whoopsSomethingWrongHappened { rollback.pointee = true return } // etc ... } catch { rollback.pointee = true print }}

(注意,从斯维夫特 3起初接纳pointee,但在Swift2.3中,使用memory实际不是pointee。)

FMDatabaseQueue将运转块。所以若是你並且从八个线程调用FMDatabaseQueue的主意,它们将根据它们被接到的相继推行。那样查询和更新将不会对对方的趾头,每八个都很欢愉。

注意:对FMDatabaseQueue方法的调用是阻塞的。所以固然你正在传递块,它们也不会在另多个线程上运转。

您能够这么做!比方,-makeFunctionNamed:在main.m中查找

七、实践查询

ARC依然手动内部存款和储蓄器管理

图片 7图片 8

您能够选拔二种中率性一种方法,在您的cocoa项目中,FMDB能够在编写翻译时候跟据你的选取编写翻译正确的code。

八、事务FMDatabase 能够起来交付业务通过调用贰个方便的法子或实行起来/结束职业的语句。

用法

多语句和批处理:你能够应用 FMDatabase 的 executestatements:withresultblock:方法在字符串去处理多说话。

FMDB中有两个基本点的类

图片 9

1.FMDatabase-代表叁个单身的SQLite数据库,试行SQL语句。

当提供三个 SQL 语句给 fmdb 时,在插入钱你不应有总计“清理”任何值。相反,你应当运用专门的学业的SQLite绑定的语法:INSERT INTO myTable VALUES (?, ?, ?, ?)

2.FMResultSet-代表FMDatebase查询的结果集

图片 10图片 11图片 12

3.FMDatabaseQueue-如若你想要在八线程中查询和立异,你应当选用那么些类,

除此以外,您也足以应用命名参数语法:INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)

创制数据库

The parameters must start with a colon. SQLite itself supports other characters, but internally the dictionary keys are prefixed with a colon, do not include the colon in your dictionary keys.

FMDatabase通过三个SQLite数据库文件的路径创造。那个门路能够有以下两种体裁:

图片 13

1.贰个系统文件路线.硬盘上事先空中楼阁的,假若它不设有,FMDB会为你新建。

The key point is that one should not use NSString method stringWithFormat to manually insert values into the SQL statement, itself. Nor should one Swift string interpolation to insert values into the SQL. Use ? placeholders for values to be inserted into the database (or used in WHERE clauses in SELECT statements).

2.一个空字符串,一个空数据库在不经常文件中开创。在数据库连接关闭的时候,那一个数据库会被去除。

九、使用 FMDatabaseQueue 和线程安全(具体参照 FMDB 的 github 的readMe )尽管采纳中接纳了八线程操作数据库,那么就须求使用 FMDatabaseQueue 来保证线程安全了。 应用中不可在八个线程中联手使用多个 FMDatabase 对象操作数据库,那样会引起数据库数据错乱。 为了八线程操作数据库安全, FMDB 使用了 FMDatabaseQueue,使用 FMDatabaseQueue 很简短,首先用一个数据库文件地方来初使化 FMDatabaseQueue,然后就足以将七个闭包传入 inDatabase 方法中。 在闭包中操作数据库,而不直接参预 FMDatabase 的保管。

3.NULL(空)。三个在内部存款和储蓄器中的数据库将被创设。在数据库连接关闭的时候,那几个数据库会被灭绝。

图片 14

想通晓更加多关于一时或内部存款和储蓄器数据库,请阅读sqlite文书档案:

CocoaPods开源库的搭建CocoaPods搭建私有库CocoaPods搭建私有库蒙受标题CocoaPods私有库的升级换代维护SKStoreReviewController之程序内评价App应用程序图标的动态调换开源框架 MGJRouter_SwiftiOS的MVP设计情势iOS插件化iOS FMDB的利用Swift之Reactive斯维夫特OC之ReactiveCocoaOC之ReactiveCocoa进级iOS 质量考虑

eg: FMDatabase *db = [FMDatabase databaseWithpath:@“/tmp/tmp.db”];

图片 15

开采数据库

和数据库建立连接此前,应该保障它是开发的,在内部存款和储蓄器不足、禁止开启、创制数据库的时候会张开退步。

if(![db open]){

[db release];

return;

}

试行更新

除去SELECT格式的数据库实施语句都是立异。包含CREATE,UPDATE,INSERT,ALTETiggo,COMMIT,BEGIN,DETACH,DELETE,DROP,END,EXPLAIN,VACUUM,还应该有replace语句等等。基本上,只要您的SQL语句不是以SELECT初叶,都是翻新语句。

实施更新再次回到贰个单一BOOL值,重回值为YES代表实施更新成功,再次回到值为NO表示发生了某些不当。你能够调用-laseErrorMessage和-laseErrorCode方法接收越来越多消息。

推行查询

三个SELECt语句是三个查询语句并且经过-executrQuery方法试行。

举办查询成功重临FMResultSet对象,退步重临nil。你应有使用-laseErrorMessage和-laseErrorCode方法分明到底干什么查询失利。

为了循环访谈查询结果集,你能够行使while()循环.你也须求从一个纪录到另一条。在FMDB中,最简易的不二等秘书籍是这么:

FMResultSet *s = [db executeQuery:@“SELECT *FROM myTable”];

while ([s next]){

//retrieve values for each record

}

平凡你在行使查询结果的再次回到值前必需先调用-[FMResultSet next],就算你只要求二次,像这么:

FMResultSet *s = [db executeQuery:@“SELECT COUNT(*) FROM myTable”];

if ([s next]) {

int totalCount = [s intForColumnIndex:0];

}

FMResultSet 拥有十分的多方式去获得适当类型的数额

intForColumn:

longForColumn:

longLongIntForColumn:

boolForColumn:

doubleForColumn:

stringForColumn:

dateForColumn:

dataForColumn:

dataNoCopyForColumn:

UTF8StringForColumnName:

objectForColumnName:

此间的每三个方法都有二个照猫画虎的{type}ForColumnIndex:表达式。基于字段在结果聚焦的地点能够被用来获取数据

,和字段名一一对应。

特地的,你在那边不须求-close三个FMResultSet,直到结果集都被保释或然父数据库关闭了。

关闭(Closing)

当你成功了数量的询问和换代,你应当-close那几个FMDatabase的连续让SQLite释放那些操作进度中据为己有的能源。

[db close];

Transactions(事务)

FMDatabase能够因而调用合适的秘诀或然实行起来和甘休事务型语句初叶并交付多个业务。

多条语句和批量增加

你能够动用FMDatabase的executeStatements:withResultBlock:去做一个多条SQL语句在贰个字符串中:

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"

"create table bulktest2 (id integer primary key autoincrement, y text);"

"create table bulktest3 (id integer primary key autoincrement, z text);"

"insert into bulktest1 (x) values ('XXX');"

"insert into bulktest2 (y) values ('YYY');"

"insert into bulktest3 (z) values ('ZZZ');";

success = [db executeStatements:sql];

sql = @"select count(*) as count from bulktest1;"

"select count(*) as count from bulktest2;"

"select count(*) as count from bulktest3;";

success = [self.db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) {

NSInteger count = [dictionary[@"count"] integerValue];

XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary);

return 0;

}];

数量管理

当提供三个SQL语句到FMDB。你应该检查每二个输入值.代替的,你能够选用标准绑定语法:

INSERT INTO myTable VALUES (?, ?, ?, ?)

?符号在SQLite标准中是二个插入的占位符。实行办法漫天的收受来自参数的变量值(只怕是这一个参数的,像NSArray,NSDictionary,大概是va_list),适当对你隐蔽。

再有,在OC中动用使用?占位符就好像这么:

NSInteger identifier = 42;

NSString *name = @"Liam O'Flaherty ("the famous Irish author")";

NSDate *date = [NSDate date];

NSString *comment = nil;

BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", @(identifier), name, date, comment ?: [NSNull null]];

if (!success) {

NSLog(@"error = %@", [db lastErrorMessage]);

}

留意:基本数据类型,像NSInteger这样的变量自负,应该用MNSNumber对象表示,须要用@语法,像上边那样。也许用[NSNumber numberWithInt:identifier]语法也得以。

别的,在SQL中NULL值应该用[NSNull null]插入.举个例证,像上边拾贰分comment自断大概为nil,你能够一利用comment ?: [NSNull null]语法,当comment为不为空是插入这些字符串,为空时插入[NSNull null].

在swift中,你应有使用executeUpdate(values:),不仅是swift的精晓语法,也长久以来是swift2的一无所能抛出句柄。

do {

let identifier = 42

let name = "Liam O'Flaherty ("the famous Irish author")"

let date = NSDate()

let comment: String? = nil

try db.executeUpdate("INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", values: [identifier, name, date, comment ?? NSNull()])

} catch {

print("error = (error)")

}

小心:在swift,你不必要像OC那样基础数字类型的卷入,可是只要你想要插入壹个可变字符串,你将索要采取那样的语法comment ?? NSNull() (i.e.,假如为nil,使用NSNull,不然使用那一个字符串)。

二选一,你能够应用named参数语法。

INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)

以此参数列表必得以冒号初叶,SQLite也帮忙别的符号,然则中间字典的key是以冒号前缀的,你字典里的key不要包蕴冒号。

NSDictionary *arguments = @{@"identifier": @(identifier), @"name": name, @"date": date, @"comment": comment ?: [NSNull null]};

BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (:identifier, :name, :date, :comment)" withParameterDictionary:arguments];

if (!success) {

NSLog(@"error = %@", [db lastErrorMessage]);

}

在SQL语句中key应该运用NSString的stringWithFormat方法手动插入对应的值。那么swift的字符串怎么做?,使用?占位符向数据库插入值(可能在SELECT语句中动用WHERE从句)

选择FMDatabaseQueue 和线程安全

在二十四线程使用同多少个FMDatabase的单例是三个坏主意。经常为每三个线程创设FMDatabase对象都以OK的,千万不要跨线程使用数据库单例,清楚不要在八线程同偶尔候使用。坏的事必须然发生你将会获得一些闪退,大概贰个万分,也许是陨石从天而至砸中了你的mac,这一个将会被抱怨。

四线程使用的时候绝不实力话单例。

用FMDatabaseQueue代替。实例化二个单例FMDatabaseQueue况且在八线程中使用.这些FMDatabaseQueue对象将通过队列管理共同施行来自二十二十四线程的通令。这里是怎么着利用,第一步,创设你的队列。

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

下一场那样使用它:

[queue inDatabase:^(FMDatabase *db) {

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

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

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

FMResultSet *rs = [db executeQuery:@"select * from foo"];

while ([rs next]) {

}

}];

简轻松单的多任务包装在一个思想政治工作中key那样做:

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

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

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

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

if (whoopsSomethingWrongHappened) {

*rollback = YES;

return;

}

// etc…

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

}];

在swift里这样:

queue.inTransaction { db, rollback in

do {

try db.executeUpdate("INSERT INTO myTable VALUES (?)", values: [1])

try db.executeUpdate("INSERT INTO myTable VALUES (?)", values: [2])

try db.executeUpdate("INSERT INTO myTable VALUES (?)", values: [3])

if whoopsSomethingWrongHappened {

rollback.memory = true

return

}

try db.executeUpdate("INSERT INTO myTable VALUES (?)", values: [4])

} catch {

rollback.memory = true

print(error)

}

}

FMDatabaseQueue将在种类号的队列(从类名开首)实行块.因而你可以同有时间调用在十六线程的多FMDatabaseQueue的点子,在各样排到的时候它们将被施行。这些艺术查询和革新并不会挤在协同,就不会出标题了。

专心:FMDatabaseQueue的点子是块时局的,因而尽管你正在块中,他们也不会跑在别的线程。

经过块自定义sqlite函数

您能够做这么些,举个例子:查看main.m里的 -makeFunctionNamed:

swift

你也得以在斯维夫特项目中采用FMDB

借使是那般,你不能够不:

1.从FMDB的src文件下拷贝相关的.m和.h文件到您的项目中。

你能够拷贝全数的公文(最轻巧易行的措施),恐怕只拷贝你需求的。最基本的你必要FMDatabase和FMResultSet。FMDatabaseAddition提供一些特出有利好用的方法,由此你恐怕也要求它。固然你要在多线程职务中利用数据库,FMdatabaseQueue也是非凡有效的。假如你挑选不要拷贝全部src文件目录下的文书,你还亟需更新FMDB.h,那是与您项指标有一无二一连。

在意,如若您拷贝了具有文件到你的项目中(推荐做法),你大概想要拖动个人文件到您的花色中,不是文件夹,因为倘诺您拖动文件夹,你将得不到关于增加桥引头文件(bridging header)的提示(看下一点)

2.假如您被唤醒创造桥引头文件,你应有创制它。就算您未有收到提醒且在此之前并不曾桥引头文件,你应有去加多叁个。

越来越多关于桥引头文件,看swift和oc混编( 斯维夫特 and Objective-C in the Same Project.)

3.在您的桥引头文件中,增多这一行。

#import "FMDB.h"

4.在try方式下使用executeQuery和executeUpdate的变量表明式带上sql和values参数,就好像上边包车型客车代码一样,这几个executeQuery和executeUpdate的译文都会抛出相应的特别在swift第22中学。

假如您依据上面包车型地铁做了,你能够用FMDatabase写swift代码,比方:

let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)

let fileURL = documents.URLByAppendingPathComponent("test.sqlite")

let database = FMDatabase(path: fileURL.path)

if !database.open() {

print("Unable to open database")

return

}

do {

try database.executeUpdate("create table test(x text, y text, z text)", values: nil)

try database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", values: ["a", "b", "c"])

try database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", values: ["e", "f", "g"])

let rs = try database.executeQuery("select x, y, z from test", values: nil)

while rs.next() {

let x = rs.stringForColumn("x")

let y = rs.stringForColumn("y")

let z = rs.stringForColumn("z")

print("x = (x); y = (y); z = (z)")

}

} catch let error as NSError {

print("failed: (error.localizedDescription)")

}

database.close()

历史

历史和转移总计在GitHub Page的CHANGES_AND_TODO_LIST.txt里可见。

贡献者

FMDB的进献者名单在Contributors.txt”中

在品种中利用FMDB,你应当心胸成为一个有辨识力的开辟者

FMDBMigrationManager,二个FMDBSQLite架构迁移管理体系

FCModel,贰个对操作SQL易取可选用的骨干数据模型。

FMDB开源的代码风格

空格,不要tab键。方括号,不要买通语法。FMDB的已经在试行方括号格式,平素维持这么的风格。

报告bug

编码时尽量减弱bug。你必要让开辟者很简短的开采你的bug并且复现。假如有用,装作那些能够有效解决bug的人援助着3个相当重要品种。为一些开源项目专门的学业,有二个新生的小婴孩,通常时候极度特别忙。

我们早就增添模版函数在main.m(FMDBReportABugFunction)在FMDB公布版本帮你消除。

通过Xcode打开fmdb项目

张开main.m函数修改FMDBReportABugFunction再次出现。

安装你的表在代码中。

认同你的查询或许是翻新

累加一些关于这么些bug的预见

接下来您能够把这几个通过邮件发给FMDB邮件表。只怕,你能够记录那些bug通过githubFMDBbug记录员。

可选的:

化解这么些bug,发送附属类小部件到邮件表,确定保证全体其余测量试验在您的退换运维之后。

支持

其一FMDB帮忙通道是三个邮件地址列表(上边有),bug提在这里,或许在Stack Overflow。所以就是,社区和自觉组织提供支撑。

FMDB开采是监视。借使FMDB对您有帮带,考虑买入二个用到FM或然告诉您的相爱的人关于它。

执照

FMDB的许可证在"License.txt”文件中

本文由pc28.am发布于计算机编程,转载请注明出处:iOS学习笔记,数据库之FMDB简单介绍

上一篇:新知识整理汇总 下一篇:没有了
猜你喜欢
热门排行
精彩图文
  • 离屏渲染优化详解,app质量优化的那个事
    离屏渲染优化详解,app质量优化的那个事
    离屏渲染的定义: 先 在显示屏外面制造新的缓冲区, 然后 渲染到纹理中, 最后 将结果渲染到日前体现荧屏的帧缓冲区中。那么为啥离屏渲染耗品质:主
  • iOS8扩展插件开发配置
    iOS8扩展插件开发配置
    Share Extension 简介 前两篇小说介绍了Application Extension运维原理、TodayExtension,本篇来介绍一下 Share Extension创制和动用。分享扩大给用提供二个有利的不二秘
  • Application Extension(二):Today Extension
    Application Extension(二):Today Extension
    简介 在公告中央的Today的视图中显得的 extension 叫做 widget ,widget能够一本万利客户神速的获取想要的音信,不用再经过复杂的步骤伸开app工夫找到自个儿想
  • Application Extension(一):介绍
    Application Extension(一):介绍
    本篇文章是对 iOS Application Extension的简单介绍。介绍的开始和结果富含:对Application Extension的品类、运营原理、申明周期、之间的通讯等。 转发请注脚出处
  • 内购模块,中沙盒账号使用注意事项
    内购模块,中沙盒账号使用注意事项
    重新提醒登入账号.png https://wilddylan.github.io/2016/09/23/IAP/ 文档: 京东开拓 1、前言 在iOS12前,借使对沙盒账号测量试验充钱不熟知的同学,大概会境遇过如此