SQLite (http://www.sqlite.org/docs.html) 是一個輕量級的關係數據庫。iOS SDK 很早就支持了 SQLite,在使用時,只須要加入 libsqlite3.dylib 依賴以及引入 sqlite3.h 頭文件便可。可是,原生的 SQLite API 在使用上至關不友好,在使用時,很是不便。因而,開源社區中就出現了一系列將 SQLite API 進行封裝的庫,而 FMDB (https://github.com/ccgus/fmdb) 則是開源社區中的優秀者。php
FMDB 在使用上至關方便。如下是一個簡單的例子:html
1
2 3 4 5 6 7 8 9 10 11 |
NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString* dbpath = [docsdir stringByAppendingPathComponent:@"user.sqlite"]; FMDatabase* db = [FMDatabase databaseWithPath:dbpath]; [db open]; FMResultSet *rs = [db executeQuery:@"select * from people"]; while ([rs next]) { NSLog(@"%@ %@", [rs stringForColumn:@"firstname"], [rs stringForColumn:@"lastname"]); } [db close]; |
能夠看到,使用 FMDB 後的數據庫代碼清晰明瞭,比原生的 API 優雅多了。另外,FMDB 同時兼容 ARC 和非 ARC 工程,會自動根據工程配置來調整相關的內存管理代碼。mysql
該使用說明主要翻譯自 fmdb 的 github 項目說明文檔: https://github.com/ccgus/fmdbgit
首先將 FMDB 從 github 上 clone 下來,而後將如下文件 copy 到你的工程中:github
1
2 3 4 5 6 7 8 9 10 |
FMDatabase.h FMDatabase.m FMDatabaseAdditions.h FMDatabaseAdditions.m FMDatabasePool.h FMDatabasePool.m FMDatabaseQueue.h FMDatabaseQueue.m FMResultSet.h FMResultSet.m |
創建數據庫只須要以下一行便可 , 當該文件不存在時,fmdb 會本身建立一個。若是你傳入的參數是空串:@「」 ,則 fmdb 會在臨時文件目錄下建立這個數據庫,若是你傳入的參數是 NULL,則它會創建一個在內存中的數據庫。sql
1
|
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; |
使用以下語句,若是打開失敗,多是權限不足或者資源不足。一般打開完操做操做後,須要調用 close 方法來關閉數據庫。數據庫
1
2 3 4 5 6 7 8 |
if (![db open]) { // error return; } // some operation // ... [db close]; |
除了 Select 操做以外,其它的都是更新操做。更新操做使用以下方法,若是有錯誤,能夠用 error 參數中得到。安全
1
|
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:] |
查詢操做示例以下。注意:即便操做結果只有一行,也須要先調用 FMResultSet 的 next 方法。多線程
1
2 3 4 5 6 7 8 9 |
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"]; while ([s next]) { //retrieve values for each record } FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"]; if ([s next]) { int totalCount = [s intForColumnIndex:0]; } |
FMDB 提供以下多個方法來獲取不一樣類型的數據:閉包
1
2 3 4 5 6 7 8 9 10 11 |
intForColumn: longForColumn: longLongIntForColumn: boolForColumn: doubleForColumn: stringForColumn: dateForColumn: dataForColumn: dataNoCopyForColumn: UTF8StringForColumnIndex: objectForColumn: |
一般狀況下,你並不須要關閉 FMResultSet,由於相關的數據庫關閉時,FMResultSet 也會被自動關閉。
一般狀況下,你能夠按照標準的 SQL 語句,用 ? 表示執行語句的參數,如:
1
|
INSERT INTO myTable VALUES (?, ?, ?) |
而後,能夠咱們能夠調用 executeUpdate 方法來將 ? 所指代的具體參數傳入,一般是用變長參數來傳遞進去的,以下:
1
2 |
NSString *sql = @"insert into User (name, password) values (?, ?)"; [db executeUpdate:sql, user.name, user.password]; |
這裏須要注意的是,參數必須是 NSObject 的子類,因此象 int,double,bool 這種基本類型,須要封裝成對應的包裝類才行,以下所示:
1
2 3 4 |
// 錯誤,42 不能做爲參數 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42]; // 正確,將 42 封裝成 NSNumber 類 [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]]; |
若是咱們的 app 須要多線程操做數據庫,那麼就須要使用 FMDatabaseQueue 來保證線程安全了。 切記不能在多個線程中共同一個 FMDatabase 對象而且在多個線程中同時使用,這個類自己不是線程安全的,這樣使用會形成數據混亂等問題。
使用 FMDatabaseQueue 很簡單,首先用一個數據庫文件地址來初使化 FMDatabaseQueue,而後就能夠將一個閉包 (block) 傳入 inDatabase 方法中。 在閉包中操做數據庫,而不直接參與 FMDatabase 的管理。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// 建立,最好放在一個單例的類中 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]]; }]; |
爲了查看 Sqlite 中的數據,一個好的圖形化界面的數據庫管理程序是必不可少的。mysql 有 phpMyAdmin,那麼 sqlite 呢?
我主要使用的是 Firefox 的一個名爲 SQLite Manager 的插件,安裝此插件後,能夠直接打開後綴名爲 sqlite 的數據庫文件。SQLite Manager 提供一個圖形化的界面來執行數據查詢或更改操做。以下圖所示:
FMDB 將 SQLite API 進行了很友好的封裝,使用上很是方便,對於那些使用純 Sqlite API 來進行數據庫操做的 app,能夠考慮將其遷移到基於 FMDB 上,這對於之後數據庫相關功能的開發維護,能夠提升很多效率。