在Swift中访问SQLite数据库

我正在寻找一种方法来访问我的应用程序中的Swift代码的SQLite数据库。

我知道我可以在Objective C中使用SQLite Wrapper,并使用桥接头,但我宁愿能够完全在Swift中完成这个项目。 有没有办法做到这一点,如果是这样,有人可以指向我的参考,显示如何提交查询,检索行等?

虽然你应该使用许多SQLite包装(我更喜欢FMDB ),如果你想知道如何自己调用SQLite库,你可以:

  1. configuration你的Swift项目来处理SQLite C调用。 如果使用Xcode 9,你可以简单地做:

    import SQLite3 

    在Xcode的早期版本中,您可以:

    • 创build桥接头文件到项目。 请参阅使用Cocoa和Objective-C的Swift中的将Objective-C导入Swift部分。 这个桥接头应该导入sqlite3.h

       #import <sqlite3.h> 
    • libsqlite3.tbd添加到您的项目中(或者更旧的版本, libsqlite3.dylib )。

  2. 创build/打开数据库。

     let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent("test.sqlite") // open database var db: OpaquePointer? if sqlite3_open(fileURL.path, &db) != SQLITE_OK { print("error opening database") } 
  3. 使用sqlite3_exec来执行SQL(例如创build表)。

     if sqlite3_exec(db, "create table if not exists test (id integer primary key autoincrement, name text)", nil, nil, nil) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error creating table: \(errmsg)") } 
  4. 使用sqlite3_prepare_v2来准备SQL ? 我们将绑定值的占位符。

     var statement: OpaquePointer? if sqlite3_prepare_v2(db, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error preparing insert: \(errmsg)") } if sqlite3_bind_text(statement, 1, "foo", -1, SQLITE_TRANSIENT) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("failure binding foo: \(errmsg)") } if sqlite3_step(statement) != SQLITE_DONE { let errmsg = String(cString: sqlite3_errmsg(db)!) print("failure inserting foo: \(errmsg)") } 

    请注意,它使用SQLITE_TRANSIENT常量,它可以如下实现 :

     internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self) internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) 
  5. 重置SQL以插入另一个值。 在这个例子中,我将插入一个NULL值:

     if sqlite3_reset(statement) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error resetting prepared statement: \(errmsg)") } if sqlite3_bind_null(statement, 1) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("failure binding null: \(errmsg)") } if sqlite3_step(statement) != SQLITE_DONE { let errmsg = String(cString: sqlite3_errmsg(db)!) print("failure inserting null: \(errmsg)") } 
  6. 完成预处理语句以恢复与该预处理语句相关联的内存:

     if sqlite3_finalize(statement) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error finalizing prepared statement: \(errmsg)") } statement = nil 
  7. 准备新的语句,通过检索值从表和循环中select值:

     if sqlite3_prepare_v2(db, "select id, name from test", -1, &statement, nil) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error preparing select: \(errmsg)") } while sqlite3_step(statement) == SQLITE_ROW { let id = sqlite3_column_int64(statement, 0) print("id = \(id); ", terminator: "") if let cString = sqlite3_column_text(statement, 1) { let name = String(cString: cString) print("name = \(name)") } else { print("name not found") } } if sqlite3_finalize(statement) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error finalizing prepared statement: \(errmsg)") } statement = nil 
  8. closures数据库:

     if sqlite3_close(db) != SQLITE_OK { print("error closing database") } db = nil 

对于Swift 2,请参阅此答案的以前的修订 。

您可以做的最好的方法是在桥接头中导入dynamic库:

  1. 将libsqlite3.dylib添加到您的“链接二进制库”构build阶段
  2. 创build一个“Bridging-Header.h”并将#import <sqlite3.h>添加到顶部
  3. 在“Swift编译器 – 代码生成”下的Build Settings中为“Objective-C Bridging Header”设置设置“Bridging-Header.h”

然后,您将能够从swift代码中访问所有的c方法,如sqlite3_open

但是,您可能只想使用FMDB并通过桥接头来导入,因为这是一个更加面向对象的sqlite包装器。 在Swift中处理C指针和结构将会非常麻烦。

我也正在寻找一些方法来与SQLite进行交互,就像我以前在Objective-C中一样。 不可否认,由于C兼容性,我只使用了直接的C API。

由于目前在Swift中不存在用于SQLite的包装器,而且上面提到的SQLiteDB代码更高一些,并且假设了一定的用法,所以我决定创build一个包装器,并在这个过程中对Swift有所了解。 你可以在这里find它: https : //github.com/chrismsimpson/SwiftSQLite 。

 var db = SQLiteDatabase(); db.open("/path/to/database.sqlite"); var statement = SQLiteStatement(database: db); if ( statement.prepare("SELECT * FROM tableName WHERE Id = ?") != .Ok ) { /* handle error */ } statement.bindInt(1, value: 123); if ( statement.step() == .Row ) { /* do something with statement */ var id:Int = statement.getIntAt(0) var stringValue:String? = statement.getStringAt(1) var boolValue:Bool = statement.getBoolAt(2) var dateValue:NSDate? = statement.getDateAt(3) } statement.finalizeStatement(); /* not called finalize() due to destructor/language keyword */ 

我创build了一个优雅的SQLite库,完全在Swift中编写,名为SwiftData 。

它的一些特点是:

  • 将对象方便地绑定到SQLstring
  • 支持事务和保存点
  • 内联error handling
  • 完全线程安全默认情况下

它提供了一个简单的方法来执行“更改”(例如INSERT,UPDATE,DELETE等):

 if let err = SD.executeChange("INSERT INTO Cities (Name, Population, IsWarm, FoundedIn) VALUES ('Toronto', 2615060, 0, '1793-08-27')") { //there was an error during the insert, handle it here } else { //no error, the row was inserted successfully } 

和“查询”(如SELECT):

 let (resultSet, err) = SD.executeQuery("SELECT * FROM Cities") if err != nil { //there was an error during the query, handle it here } else { for row in resultSet { if let name = row["Name"].asString() { println("The City name is: \(name)") } if let population = row["Population"].asInt() { println("The population is: \(population)") } if let isWarm = row["IsWarm"].asBool() { if isWarm { println("The city is warm") } else { println("The city is cold") } } if let foundedIn = row["FoundedIn"].asDate() { println("The city was founded in: \(foundedIn)") } } } 

随着更多的function!

你可以在这里查看

还有另一个Swift 2和Swift 3的SQLite包装: http : //github.com/groue/GRDB.swift

特征:

  • ccgus / fmdb用户看起来很熟悉的API

  • 一个利用Swift标准库的低级SQLite API

  • 一个漂亮的SQL过敏开发人员的Swift查询界面

  • 支持SQLite WAL模式,并发数据库访问以获得额外的性能

  • 一个Record类,包装结果集,吃早餐的自定义SQL查询,并提供基本的CRUD操作

  • Swifttypes自由:select适合您的数据的正确的Swifttypes。 在需要的时候使用Int64,或者坚持使用方便的Int。 存储并阅读NSDate或NSDateComponents。 声明离散数据types的Swift枚举。 定义您自己的数据库可转换types。

  • 数据库迁移

  • 速度: https : //github.com/groue/GRDB.swift/wiki/Performance

AppDelegate.swift

 func createDatabase() { var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) let directory:String=path[0] let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite") print(DBpath) if (FileManager.default.fileExists(atPath: DBpath)) { print("Successfull database create") } else { let pathfrom:String=(Bundle.main.resourcePath! as NSString).appendingPathComponent("Food.sqlite") var success:Bool do { try FileManager.default.copyItem(atPath: pathfrom, toPath: DBpath) success = true } catch _ { success = false } if !success { print("database not create ") } else { print("Successfull database new create") } } } 

Database.swift

 import UIKit class database: NSObject { func databasePath() -> NSString { var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) let directory:String=path[0] let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite") if (FileManager.default.fileExists(atPath: DBpath)) { return DBpath as NSString } return DBpath as NSString } func ExecuteQuery(_ str:String) -> Bool { var result:Bool=false let DBpath:String=self.databasePath() as String var db: OpaquePointer? = nil var stmt:OpaquePointer? = nil let strExec=str.cString(using: String.Encoding.utf8) if (sqlite3_open(DBpath, &db)==SQLITE_OK) { if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK) { if (sqlite3_step(stmt) == SQLITE_DONE) { result=true } } sqlite3_finalize(stmt) } sqlite3_close(db) return result } func SelectQuery(_ str:String) -> Array<Dictionary<String,String>> { var result:Array<Dictionary<String,String>>=[] let DBpath:String=self.databasePath() as String var db: OpaquePointer? = nil var stmt:OpaquePointer? = nil let strExec=str.cString(using: String.Encoding.utf8) if ( sqlite3_open(DBpath,&db) == SQLITE_OK) { if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { var i:Int32=0 let icount:Int32=sqlite3_column_count(stmt) var dict=Dictionary<String, String>() while i < icount { let strF=sqlite3_column_name(stmt, i) let strV = sqlite3_column_text(stmt, i) let rFiled:String=String(cString: strF!) let rValue:String=String(cString: strV!) //let rValue=String(cString: UnsafePointer<Int8>(strV!)) dict[rFiled] = rValue i += 1 } result.insert(dict, at: result.count) } sqlite3_finalize(stmt) } sqlite3_close(db) } return result } func AllSelectQuery(_ str:String) -> Array<Model> { var result:Array<Model>=[] let DBpath:String=self.databasePath() as String var db: OpaquePointer? = nil var stmt:OpaquePointer? = nil let strExec=str.cString(using: String.Encoding.utf8) if ( sqlite3_open(DBpath,&db) == SQLITE_OK) { if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { let mod=Model() mod.id=String(cString: sqlite3_column_text(stmt, 0)) mod.image=String(cString: sqlite3_column_text(stmt, 1)) mod.name=String(cString: sqlite3_column_text(stmt, 2)) mod.foodtype=String(cString: sqlite3_column_text(stmt, 3)) mod.vegtype=String(cString: sqlite3_column_text(stmt, 4)) mod.details=String(cString: sqlite3_column_text(stmt, 5)) result.insert(mod, at: result.count) } sqlite3_finalize(stmt) } sqlite3_close(db) } return result } } 

Model.swift

 import UIKit class Model: NSObject { var uid:Int = 0 var id:String = "" var image:String = "" var name:String = "" var foodtype:String = "" var vegtype:String = "" var details:String = "" var mealtype:String = "" var date:String = "" } 

Access数据库:

 let DB=database() var mod=Model() 

数据库查询起火:

 var DailyResult:Array<Model> = DB.AllSelectQuery("select * from food where foodtype == 'Sea Food' ORDER BY name ASC") 

我写了一个用Swift编写的SQLite3封装库 。

这实际上是一个非常简单的API封装器,但无论如何,它具有低级的C inter-op代码,我在这里发布一个(简化的)部分来显示C inter-op。

  struct C { static let NULL = COpaquePointer.null() } func open(filename:String, flags:OpenFlag) { let name2 = filename.cStringUsingEncoding(NSUTF8StringEncoding)! let r = sqlite3_open_v2(name2, &_rawptr, flags.value, UnsafePointer<Int8>.null()) checkNoErrorWith(resultCode: r) } func close() { let r = sqlite3_close(_rawptr) checkNoErrorWith(resultCode: r) _rawptr = C.NULL } func prepare(SQL:String) -> (statements:[Core.Statement], tail:String) { func once(zSql:UnsafePointer<Int8>, len:Int32, inout zTail:UnsafePointer<Int8>) -> Core.Statement? { var pStmt = C.NULL let r = sqlite3_prepare_v2(_rawptr, zSql, len, &pStmt, &zTail) checkNoErrorWith(resultCode: r) if pStmt == C.NULL { return nil } return Core.Statement(database: self, pointerToRawCStatementObject: pStmt) } var stmts:[Core.Statement] = [] let sql2 = SQL as NSString var zSql = UnsafePointer<Int8>(sql2.UTF8String) var zTail = UnsafePointer<Int8>.null() var len1 = sql2.lengthOfBytesUsingEncoding(NSUTF8StringEncoding); var maxlen2 = Int32(len1)+1 while let one = once(zSql, maxlen2, &zTail) { stmts.append(one) zSql = zTail } let rest1 = String.fromCString(zTail) let rest2 = rest1 == nil ? "" : rest1! return (stmts, rest2) } func step() -> Bool { let rc1 = sqlite3_step(_rawptr) switch rc1 { case SQLITE_ROW: return true case SQLITE_DONE: return false default: database.checkNoErrorWith(resultCode: rc1) } } func columnText(at index:Int32) -> String { let bc = sqlite3_column_bytes(_rawptr, Int32(index)) let cs = sqlite3_column_text(_rawptr, Int32(index)) let s1 = bc == 0 ? "" : String.fromCString(UnsafePointer<CChar>(cs))! return s1 } func finalize() { let r = sqlite3_finalize(_rawptr) database.checkNoErrorWith(resultCode: r) _rawptr = C.NULL } 

如果你想要这个低级包装的完整源代码,请参阅这些文件。

configuration您的Swift项目来处理SQLite C调用:

创build桥接头文件到项目。 请参阅使用Cocoa和Objective-C的Swift中的将Objective-C导入Swift部分。 这个桥接头应该导入sqlite3.h:

将libsqlite3.0.dylib添加到您的项目。 请参阅苹果有关将库/框架添加到项目的文档。

并使用下面的代码

  func executeQuery(query: NSString ) -> Int { if sqlite3_open(databasePath! as String, &database) != SQLITE_OK { println("Databse is not open") return 0 } else { query.stringByReplacingOccurrencesOfString("null", withString: "") var cStatement:COpaquePointer = nil var executeSql = query as NSString var lastId : Int? var sqlStatement = executeSql.cStringUsingEncoding(NSUTF8StringEncoding) sqlite3_prepare_v2(database, sqlStatement, -1, &cStatement, nil) var execute = sqlite3_step(cStatement) println("\(execute)") if execute == SQLITE_DONE { lastId = Int(sqlite3_last_insert_rowid(database)) } else { println("Error in Run Statement :- \(sqlite3_errmsg16(database))") } sqlite3_finalize(cStatement) return lastId! } } func ViewAllData(query: NSString, error: NSError) -> NSArray { var cStatement = COpaquePointer() var result : AnyObject = NSNull() var thisArray : NSMutableArray = NSMutableArray(capacity: 4) cStatement = prepare(query) if cStatement != nil { while sqlite3_step(cStatement) == SQLITE_ROW { result = NSNull() var thisDict : NSMutableDictionary = NSMutableDictionary(capacity: 4) for var i = 0 ; i < Int(sqlite3_column_count(cStatement)) ; i++ { if sqlite3_column_type(cStatement, Int32(i)) == 0 { continue } if sqlite3_column_decltype(cStatement, Int32(i)) != nil && strcasecmp(sqlite3_column_decltype(cStatement, Int32(i)), "Boolean") == 0 { var temp = sqlite3_column_int(cStatement, Int32(i)) if temp == 0 { result = NSNumber(bool : false) } else { result = NSNumber(bool : true) } } else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_INTEGER { var temp = sqlite3_column_int(cStatement,Int32(i)) result = NSNumber(int : temp) } else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_FLOAT { var temp = sqlite3_column_double(cStatement,Int32(i)) result = NSNumber(double: temp) } else { if sqlite3_column_text(cStatement, Int32(i)) != nil { var temp = sqlite3_column_text(cStatement,Int32(i)) result = String.fromCString(UnsafePointer<CChar>(temp))! var keyString = sqlite3_column_name(cStatement,Int32(i)) thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!) } result = NSNull() } if result as! NSObject != NSNull() { var keyString = sqlite3_column_name(cStatement,Int32(i)) thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!) } } thisArray.addObject(NSMutableDictionary(dictionary: thisDict)) } sqlite3_finalize(cStatement) } return thisArray } func prepare(sql : NSString) -> COpaquePointer { var cStatement:COpaquePointer = nil sqlite3_open(databasePath! as String, &database) var utfSql = sql.UTF8String if sqlite3_prepare(database, utfSql, -1, &cStatement, nil) == 0 { sqlite3_close(database) return cStatement } else { sqlite3_close(database) return nil } } } 

有时, sqlite.org上显示的Swift版本的“5分钟或更less的SQLite”方法就足够了。 “5分钟或更less”的方法使用sqlite3_exec() ,这是sqlite3_prepare()sqlite3_step()sqlite3_column()sqlite3_finalize()的便捷包装。

Swift 2.2可以直接支持sqlite3_exec() callback函数指针,作为一个全局的,非实例的过程func或一个非捕获的文字闭包{}

可读的typealias

 typealias sqlite3 = COpaquePointer typealias CCharHandle = UnsafeMutablePointer<UnsafeMutablePointer<CChar>> typealias CCharPointer = UnsafeMutablePointer<CChar> typealias CVoidPointer = UnsafeMutablePointer<Void> 

callback方法

 func callback( resultVoidPointer: CVoidPointer, // void *NotUsed columnCount: CInt, // int argc values: CCharHandle, // char **argv columns: CCharHandle // char **azColName ) -> CInt { for i in 0 ..< Int(columnCount) { guard let value = String.fromCString(values[i]) else { continue } guard let column = String.fromCString(columns[i]) else { continue } print("\(column) = \(value)") } return 0 // status ok } func sqlQueryCallbackBasic(argc: Int, argv: [String]) -> Int { var db: sqlite3 = nil var zErrMsg:CCharPointer = nil var rc: Int32 = 0 // result code if argc != 3 { print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0])) return 1 } rc = sqlite3_open(argv[1], &db) if rc != 0 { print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" ) sqlite3_close(db) return 1 } rc = sqlite3_exec(db, argv[2], callback, nil, &zErrMsg) if rc != SQLITE_OK { print("ERROR: sqlite3_exec " + String.fromCString(zErrMsg)! ?? "") sqlite3_free(zErrMsg) } sqlite3_close(db) return 0 } 

closures方法

 func sqlQueryClosureBasic(argc argc: Int, argv: [String]) -> Int { var db: sqlite3 = nil var zErrMsg:CCharPointer = nil var rc: Int32 = 0 if argc != 3 { print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0])) return 1 } rc = sqlite3_open(argv[1], &db) if rc != 0 { print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" ) sqlite3_close(db) return 1 } rc = sqlite3_exec( db, // database argv[2], // statement { // callback: non-capturing closure resultVoidPointer, columnCount, values, columns in for i in 0 ..< Int(columnCount) { guard let value = String.fromCString(values[i]) else { continue } guard let column = String.fromCString(columns[i]) else { continue } print("\(column) = \(value)") } return 0 }, nil, &zErrMsg ) if rc != SQLITE_OK { let errorMsg = String.fromCString(zErrMsg)! ?? "" print("ERROR: sqlite3_exec \(errorMsg)") sqlite3_free(zErrMsg) } sqlite3_close(db) return 0 } 

为了准备一个Xcode项目来调用C语言库(如SQLite),需要(1)添加一个Bridging-Header.h文件引用C头文件,如#import "sqlite3.h" ,(2)将Bridging-Header.h (3)将libsqlite3.tbd添加到链接二进制库目标设置中。

sqlite.org的“5分钟或更 短时间内的SQLite”示例在Swift Xcode7项目中实现。

你也可以简单的使用单个类来快速的configurationSQLite。

参考

https://github.com/hasyapanchasara/SQLite_SingleManagerClass

创build数据库的方法

 func methodToCreateDatabase() -> NSURL?{} 

插入,更新和删除数据的方法

 func methodToInsertUpdateDeleteData(strQuery : String) -> Bool{} 

select数据的方法

 func methodToSelectData(strQuery : String) -> NSMutableArray{} 

你可以在Swift中使用这个库,用于SQLite https://github.com/pmurphyjam/SQLiteDemo

SQLiteDemo

使用Swift和Swift编写的SQLDataAccess类的SQLite Demo

添加到您的项目

你只需要三个文件添加到你的项目* SQLDataAccess.swift * DataConstants.swift * Bridging-Header.h Bridging-Header必须在你的Xcode的项目'Objective-C Bridging Header'在'Swift Compiler – General'

使用示例

只需按照ViewController.swift中的代码来查看如何使用SQLDataAccess.swift编写简单的SQL首先,您需要打开您处理的SQLite数据库

 ```swift let db = SQLDataAccess.shared db.setDBName(name:"SQLite.db") let opened = db.openConnection(copyFile:true) ``` 

如果openConnection成功,现在你可以做一个简单的插入到表格AppInfo中

 ```swift //Insert into Table AppInfo let status = db.executeStatement("insert into AppInfo (name,value,descrip,date) values(?,?,?,?)", ”SQLiteDemo","1.0.2","unencrypted",Date()) if(status) { //Read Table AppInfo into an Array of Dictionaries let results = db.getRecordsForQuery("select * from AppInfo ") NSLog("Results = \(results)") } ``` 

看看有多简单!

db.executeStatement中的第一项是SQL作为string,后面的所有术语都是Anytypes的可变参数列表,并且是Array中的参数。 所有这些术语在SQL参数列表中用逗号分隔。 您可以在后续语句之后立即inputstring,整数,date和Blob,因为所有这些术语都被认为是续集的参数。 可变参数数组只是方便地在一个executeStatement或getRecordsForQuery调用中input所有的续集。 如果您没有任何参数,请不要在SQL之后input任何内容。

结果数组是一个Dictionary的数组,其中'key'是您的表列的名称,'value'是您从SQLite获取的数据。 您可以使用for循环轻松地遍历此数组,或者直接打印出来,或将这些Dictionary元素分配给在视图控制器中用于模型消耗的自定义数据对象类。

 ```swift for dic in results as! [[String:AnyObject]] { print(“result = \(dic)”) } ``` 

SQLDataAccess将存储文本,double,float,blob,Date,整数和long long整数。 对于Blob,你可以存储二进制,varbinary,blob。

对于文本,你可以存储字符,字符,clob,国家不同字符,本地字符,nchar,nvarchar,varchar,variant,变化字符,文本。

对于date,您可以存储date时间,时间,时间戳,date。

对于整数,你可以存储bigint,bit,bool,boolean,int2,int8,integer,mediumint,smallint,tinyint,int。

对于双精度,您可以存储小数点,双精度,浮点数,实数,双精度。 双精度最高。

你甚至可以存储Nulltypes的空值。

在ViewController.swift中,一个更复杂的例子就是如何将字典插入为“Blob”。 此外SQLDataAccess理解本机Swift Date(),所以你可以插入这些对象与转换,它会将它们转换为文本并存储它们,并在检索时将它们从文本转换回date。

当然,SQLite的真正的力量是它的交易能力。 这里你可以从字面上用参数排队400个SQL语句,并且一次插入所有的SQL语句,因为速度非常快。 ViewController.swift也向你展示了如何做到这一点的例子。 所有你真正要做的就是创build一个名为“sqlAndParams”的字典数组,在这个数组中你存储字典有两个键“SQL”用于string续集语句或查询,而“PARAMS”只是一个本地对象数组SQLite了解该查询。 然后,将每个'sqlParams'作为一个单独的续集查询字典和参数存储在'sqlAndParams'数组中。 一旦你创build了这个数组,你只需要调用。

 ```swift let status = db.executeTransaction(sqlAndParams) if(status) { //Read Table AppInfo into an Array of Dictionaries for the above Transactions let results = db.getRecordsForQuery("select * from AppInfo ") NSLog("Results = \(results)") } ``` 

另外,所有executeStatement和getRecordsForQuery方法都可以使用简单的String for SQL查询和Array查询所需的参数来完成。

 ```swift let sql : String = "insert into AppInfo (name,value,descrip) values(?,?,?)" let params : Array = ["SQLiteDemo","1.0.0","unencrypted"] let status = db.executeStatement(sql, withParameters: params) if(status) { //Read Table AppInfo into an Array of Dictionaries for the above Transactions let results = db.getRecordsForQuery("select * from AppInfo ") NSLog("Results = \(results)") } ``` 

一个Objective-C版本也存在,被称为相同的SQLDataAccess,所以现在你可以select在Objective-C或Swift中编写你的续集。 另外SQLDataAccess也可以和SQLCipher一起工作,目前的代码还没有安装,但是这样做很容易,一个如何实现的例子实际上就是Objective-C版本的SQLDataAccess。

SQLDataAccess是一个非常快速和高效的类,可以用来替代CoreData,它真的只是使用SQLite作为其基础数据存储,而不需要CoreData附带的所有CoreData核心数据完整性故障崩溃。