美文网首页
iOS数据库之FMDB的使用

iOS数据库之FMDB的使用

作者: 南衍儿 | 来源:发表于2017-11-29 14:17 被阅读0次

iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB,PlausibleDatabase等.

安装


使用CocoaPods来安装FMDB

CocoaPods是Swift和Objective-C Cocoa项目的依赖管理器。它拥有4万多个库,用于超过280万个应用程序。CocoaPods可以帮助您优雅地扩展您的项目。

如果你没有创建CocoaPods工程,在工程目录下使用

$ pod init

来初始化项目,在生成的Podfile文件中添加FMDB:

target 'MyApp' do
    pod 'FMDB'
    # pod 'FMDB/FTS'   # FMDB with FTS
    # pod 'FMDB/standalone'   # FMDB with latest SQLite amalgamation source
    # pod 'FMDB/standalone/FTS'   # FMDB with latest SQLite amalgamation source and FTS
    # pod 'FMDB/SQLCipher'   # FMDB with SQLCipher
end

然后执行

$ pod install

然后使用新生成的*.xcworkspace工程,而不是*.xcodeproj

用法


在FMDB中有三个主要的类;

  • FMDataase-表示一个SQLite数据库.用于执行SQLite语句
  • FMResultSet-表示数据库的查询结果
  • FMDatabaseQueue-在多个线程来执行查询和更新时会使用这个类

创建数据库

需要制定一个文件路径(path)来创建一个给予SQLite的FMDatabase,有以下三种方式可以指定文件路径:

  • 指定一个文件路径,如果文件不存在,则自动创建
  • 指定路径为一个空字符串(@""),使用该方式会创建一个临时数据库文件,当FMDatabase被关闭的时候,临时数据库文件自动被删除
  • NULL 会在内存中创建一个临时数据库,在FMDatabase被关闭的时候自动删除
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];
FMDatabase *db = [FMDatabase databaseWithPath:path];

打开数据库

在与数据库进行交互之前,我们需要打开数据库,如果没有足够的资源或权限打开和/或创建数据库,则打开失败,当打开失败的时候,把db置为nil.

if(![db open]){
db = nil;
return ;
}

执行更新

除了SELECT操作外,SQLite的所有命令都使用executeUpdate消息来执行.包括CREATE, UPDATE, INSERT, ALTER, COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM,REPLACE等,只要你不是执行SELECT语句,就是更新数据库操作.

BOOL succ = [db executeUpdate:sql]; //sql是SQLite命令语句字符串

执行更新会返回一个布尔值。返回值YES意味着更新成功执行,返回值NO意味着遇到了一些错误。可以调用lastErrorMessagelastErrorCode方法来检索更多的信息。

执行查询

一个SELECT语句是一个查询,并通过其中一种-executeQuery...方法执行。
如果成功执行查询则返回一个FMResultSet对象,失败返回nil。可以使用lastErrorMessagelastErrorCode方法来确定查询失败的原因。
为了迭代你的查询的结果,可以用一个while()循环,在循环中使用next方法来不断取出结果.

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

即使你只希望查询一个值也需要使用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:
  • UTF8StringForColumn:
  • objectForColumn:
    例如,取出一个NSStringname数据
NSString *name = [s stringForColumn:@"name"];

每个方法还有一个对应的{type}ForColumnIndex:变量,用来根据结果中列的位置来检索数据,而不是列名。
通常情况下没有必要手动关闭FMResultSet对象,因为出现这种情况可以当结果集被释放,或者数据库被关闭自动关闭.

关闭数据库

当你完成对数据库的查询和更新时,你应该close关闭对FMDatabase连接,这样SQLite将释放资源。

[db close];

事务(Transactions)

FMDatabase可以使用begincommit来包裹一个事务

多个语句的执行

FMDatabase可以一次执行多个语句和用block进行操作

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 VLUEA (?,?,?,?)

?字符被SQLite识别为要插入的值的占位符。

NSInteger identifier = 42;
NSString *name = @"Liam O'Flaherty ";
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),应该作为一个NSNumber对象,通过一个语法糖@()来完成NSIntegerNSNumber的转变
同样的SQL中的NULL值应该使用[NSNull null]来代替,如上面实例代码中的comment,使用comment ?:[NSNull null]来代替nil.

或者,也可以使用命名参数语法,当传入一个字典类型的时候尤其适用:

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

参数必须以:开头

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]);
}

关键是不应该使用NSString方法stringWithFormat手动将值插入到SQL语句本身。

使用FMDatabaseQueue和线程安全

不要在多个线程中同时使用一个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]) {
        …
    }
}];

一种简单的事务的处理方法:

[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 ...
}];

注意:FMDatabaseQueue方法的调用是阻塞的,所以你传递的^block,不会在另一个线程上运行.

相关文章

  • 【转·链接】iOS FMDB对数据库进行加密

    iOS - 使用FMDB进行数据库加密iOS FMDB数据库加密相关

  • Swift中使用FMDB IOS

    18-(掌握)FMDB基本使用 什么是FMDB?FMDB是iOS平台的SQLite数据库框架FMDB以OC的方式封...

  • SQLite数据库框架之FMDB(Swift)

    FMDB使用 FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API ...

  • FMDB

    # FMDB基本使用 FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言...

  • iOS数据存储之FMDB

    FMDB介绍 FMDB是iOS平台的SQLite数据库框架FMDB以OC的方式封装了SQLite的C语言API使用...

  • iOS_FMDB

    FMDB:FMDB是iOS平台的SQLite数据库框架 FMDB的优势:使用起来更加面向对象,省去了很多麻烦、冗余...

  • iOS开发之FMDB的使用

    开发中,使用到数据库一般会使用FMDB这个第三方库,来简化使用。FMDB是iOS平台的SQLite数据库框架,它以...

  • FMDB 数据库的使用-OC篇

    FMDB是iOS数据库的一种 是对 sqlist 数据库的再次封装. FMDB数据库使用的更加简单方便 1 FMD...

  • iOS开发中FMDB的基本操作介绍(转载)

    iOS开发数据库篇—FMDB简单介绍 一、简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框...

  • iOS-FMDB详解及使用

    一 FMDB简介 什么是 FMDB FMDB 是 iOS 平台的 SQLite 数据库框架 FMDB 以 OC 的...

网友评论

      本文标题:iOS数据库之FMDB的使用

      本文链接:https://www.haomeiwen.com/subject/nycubxtx.html