Accesso a un database SQLite in Swift

Sto cercando un modo per accedere a un database SQLite nella mia app con il codice Swift.

So che posso utilizzare un wrapper SQLite in Objective C e utilizzare l’intestazione del bridging, ma preferirei essere in grado di eseguire interamente questo progetto in Swift. C’è un modo per farlo, se è così, qualcuno può indicarmi un riferimento che mostra come inviare una query, recuperare le righe, ecc.?

Mentre probabilmente dovresti usare uno dei tanti wrapper SQLite (io preferisco FMDB , me stesso), se volessi sapere come chiamare da solo la libreria SQLite, dovresti:

  1. Configura il tuo progetto Swift per gestire le chiamate C di SQLite. Se usi Xcode 9, puoi semplicemente fare:

    import SQLite3 

    Nelle versioni precedenti di Xcode, puoi:

    • Crea un file di intestazione per bridging nel progetto. Vedi l’ Importazione di Objective-C nella sezione Swift di Using Swift con Cocoa e Objective-C . Questa intestazione di bridging dovrebbe importare sqlite3.h :

       #import  
    • Aggiungi libsqlite3.tbd (o anche per versioni precedenti, libsqlite3.dylib ) al tuo progetto:

      inserisci la descrizione dell'immagine qui

  2. Crea / apri database.

     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. Usa sqlite3_exec per eseguire SQL (ad esempio crea una tabella).

     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. Utilizzare sqlite3_prepare_v2 per preparare SQL con ? segnaposto a cui legheremo valore.

     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)") } 

    Nota, che utilizza la costante SQLITE_TRANSIENT che può essere implementata come segue:

     internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self) internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self) 
  5. Reimposta SQL per inserire un altro valore. In questo esempio, inserirò un valore 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. Finalizzare la dichiarazione preparata per recuperare la memoria associata a quella dichiarazione preparata:

     if sqlite3_finalize(statement) != SQLITE_OK { let errmsg = String(cString: sqlite3_errmsg(db)!) print("error finalizing prepared statement: \(errmsg)") } statement = nil 
  7. Prepara una nuova istruzione per la selezione dei valori da tabella e loop attraverso il recupero dei valori:

     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. Chiudi database:

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

Per Swift 2, vedere la revisione precedente di questa risposta .

Il meglio che puoi fare è importare la libreria dynamic all’interno di un’intestazione di bridging:

  1. Aggiungi libsqlite3.dylib alla fase di costruzione “Link Binary With Libraries”
  2. Crea un “Bridging-Header.h” e aggiungi #import all’inizio
  3. imposta “Bridging-Header.h” per l’impostazione “Intestazione Bridging Objective-C” in Impostazioni di compilazione sotto “Compilatore Swift – Generazione del codice”

Sarai quindi in grado di accedere a tutti i metodi c come sqlite3_open dal tuo codice rapido.

Tuttavia, si può semplicemente voler usare FMDB e importarlo tramite l’intestazione del bridging in quanto si tratta di un wrapper orientato agli oggetti di sqlite. Trattare con puntatori e strutture C sarà ingombrante in Swift.

Anch’io stavo cercando un modo per interagire con SQLite nello stesso modo in cui ero abituato a fare in precedenza in Objective-C. A dire il vero, a causa della compatibilità con C, ho appena usato l’API C diritta.

Poiché attualmente non esiste alcun wrapper per SQLite in Swift e il codice SQLiteDB sopra menzionato va un po ‘più alto e presuppone un certo utilizzo, ho deciso di creare un wrapper e acquisire familiarità con Swift nel processo. Puoi trovarlo qui: 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 */ 

Ho creato un’elegante libreria SQLite scritta completamente in Swift chiamata SwiftData .

Alcune delle sue funzionalità sono:

  • Associare oggetti alla stringa di SQL
  • Supporto per transazioni e punti di salvataggio
  • Gestione degli errori in linea
  • Completamente sicuro per impostazione predefinita

Fornisce un modo semplice per eseguire “modifiche” (ad es. INSERT, UPDATE, DELETE, ecc.):

 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 } 

e ‘query’ (es. SELEZIONA):

 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)") } } } 

Insieme a molte altre funzionalità!

Puoi verificarlo qui

Ancora un altro wrapper SQLite per Swift 2 e Swift 3: http://github.com/groue/GRDB.swift

Caratteristiche:

  • Un’API che apparirà familiare agli utenti di ccgus / fmdb

  • Un’API SQLite di basso livello che sfrutta la libreria standard di Swift

  • Un’interfaccia di query piuttosto rapida per gli sviluppatori allergici a SQL

  • Supporto per la modalità SQL WAL e accesso simultaneo al database per prestazioni extra

  • Una class Record che racchiude i set di risultati, mangia le query SQL personalizzate per la colazione e fornisce operazioni CRUD di base

  • Libertà di tipo rapida: scegli il giusto tipo di Swift adatto ai tuoi dati. Utilizzare Int64 quando necessario, o attenersi alla pratica Int. Archivia e leggi NSDate o NSDateComponents. Dichiarare le enunciazioni Swift per i tipi di dati discreti. Definisci i tuoi tipi di database convertibili.

  • Migrazioni del database

  • Velocità: 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> { var result:Array>=[] 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() 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(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 { var result:Array=[] 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 = "" } 

Database di accesso:

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

database Query fire:

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

Ho scritto una libreria wrapper SQLite3 scritta in Swift .

Questo è in realtà un wrapper di altissimo livello con API molto semplice, ma in ogni caso, ha un codice inter-op C di basso livello, e pubblico qui una parte (semplificata) per mostrare l’interoperabilità C.

  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.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, len:Int32, inout zTail:UnsafePointer) -> 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(sql2.UTF8String) var zTail = UnsafePointer.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(cs))! return s1 } func finalize() { let r = sqlite3_finalize(_rawptr) database.checkNoErrorWith(resultCode: r) _rawptr = C.NULL } 

Se vuoi un codice sorgente completo di questo wrapper di basso livello, guarda questi file.

Configura il tuo progetto Swift per gestire le chiamate C di SQLite:

Crea un file di intestazione per bridging nel progetto. Vedi l’Importazione di Objective-C nella sezione Swift di Using Swift con Cocoa e Objective-C. Questa intestazione di bridging dovrebbe importare sqlite3.h:

Aggiungi la libsqlite3.0.dylib al tuo progetto. Vedi la documentazione di Apple sull’aggiunta di libreria / framework al proprio progetto.

e usato il seguente codice

  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(temp))! var keyString = sqlite3_column_name(cStatement,Int32(i)) thisDict.setObject(result, forKey: String.fromCString(UnsafePointer(keyString))!) } result = NSNull() } if result as! NSObject != NSNull() { var keyString = sqlite3_column_name(cStatement,Int32(i)) thisDict.setObject(result, forKey: String.fromCString(UnsafePointer(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 } } } 

A volte, una versione di Swift dell’approccio “SQLite in 5 minuti o meno” mostrato su sqlite.org è sufficiente. L’approccio “5 minuti o meno” usa sqlite3_exec() che è un comodo wrapper per sqlite3_prepare() , sqlite3_step() , sqlite3_column() e sqlite3_finalize() .

Swift 2.2 può supportare direttamente il puntatore della funzione callback sqlite3_exec() come una func procedura globale, non istanza o una chiusura letterale non acquisibile {} .

typealias leggibili

 typealias sqlite3 = COpaquePointer typealias CCharHandle = UnsafeMutablePointer> typealias CCharPointer = UnsafeMutablePointer typealias CVoidPointer = UnsafeMutablePointer 

Approccio alla prenotazione

 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 } 

Approccio di chiusura

 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 } 

Per preparare un progetto Xcode per chiamare una libreria C come SQLite, è necessario (1) aggiungere un'intestazione C di riferimento di file Bridging-Header.h come #import "sqlite3.h" , (2) aggiungere Bridging-Header.h a Objective-C Bridging Header nelle impostazioni del progetto e (3) aggiunge libsqlite3.tbd alle impostazioni di destinazione Link Binary With Library .

L' esempio "SQLite in 5 minuti o meno" di sqlite.org è implementato in un progetto Swift Xcode7 qui .

Puoi anche configurare SQLite con swift usando la class single ton.

Fare riferimento

https://github.com/hasyapanchasara/SQLite_SingleManagerClass

Metodo per creare un database

 func methodToCreateDatabase() -> NSURL?{} 

Metodo per inserire, aggiornare ed eliminare i dati

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

Metodo per selezionare i dati

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

Puoi usare questa libreria in Swift per SQLite https://github.com/pmurphyjam/SQLiteDemo

SQLiteDemo

Demo SQLite che utilizza Swift con la class SQLDataAccess scritta in Swift

Aggiunta al tuo progetto

Hai solo bisogno di tre file da aggiungere al tuo progetto * SQLDataAccess.swift * DataConstants.swift * Bridging-Header.h Bridging-Header deve essere impostato nel progetto Xcode ‘Objective-C Bridging Header’ sotto ‘Swift Compiler – General’

Esempi per l’uso

Basta seguire il codice in ViewController.swift per vedere come scrivere semplici SQL con SQLDataAccess.swift Innanzitutto devi aprire il Database SQLite con cui ti rapporti

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

Se openConnection ha avuto successo, ora puoi fare un semplice inserimento in Table 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)") } ``` 

Guarda com’è stato semplice!

Il primo termine in db.executeStatement è il tuo SQL come String, tutti i termini che seguono sono un elenco di argomenti variadici di tipo Any e sono i tuoi parametri in una matrice. Tutti questi termini sono separati da virgole nella tua lista di argomenti SQL. È ansible inserire stringhe, numeri interi, date e blob subito dopo l’istruzione sequel poiché tutti questi termini sono considerati parametri per il sequel. L’array di argomenti variadico rende conveniente inserire tutto il sequel in una sola chiamata executeStatement o getRecordsForQuery. Se non si dispone di parametri, non immettere nulla dopo l’SQL.

La matrice dei risultati è una matrice di dizionario in cui la ‘chiave’ è il nome della colonna delle tabelle e il ‘valore’ sono i dati ottenuti da SQLite. Si può facilmente iterare attraverso questo array con un ciclo for o stamparlo direttamente o assegnare questi elementi del dizionario all’object dati personalizzato Classi che si usano nei View Controller per il consumo del modello.

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

SQLDataAccess memorizzerà, testo, doppio, float, blob, data, intero e interi long long. Per Blob è ansible memorizzare binary, varbinary, blob.

Per il testo è ansible memorizzare char, character, clob, carattere variabile nazionale, carattere nativo, nchar, nvarchar, varchar, variante, carattere variabile, testo.

Per le date è ansible memorizzare data / ora, ora, data / ora, data.

Per i numeri interi è ansible memorizzare bigint, bit, bool, booleano, int2, int8, intero, medio, smallint, tinyint, int.

Per il doppio è ansible memorizzare decimale, doppia precisione, virgola mobile, numerico, reale, doppio. Il doppio ha la massima precisione.

È anche ansible memorizzare Null di tipo Null.

In ViewController.swift viene mostrato un esempio più complesso che mostra come inserire un dizionario come “Blob”. Inoltre, SQLDataAccess comprende lo Swift Date () nativo, quindi è ansible inserire questi oggetti senza conversione e convertirli in testo e archiviarli e, una volta recuperati, convertirli da testo a Data.

Ovviamente il vero potere di SQLite è la sua capacità di transazione. Qui puoi letteralmente accodare 400 istruzioni SQL con parametri e inserirli tutti in una volta, il che è molto potente dato che è così veloce. ViewController.swift ti mostra anche un esempio di come farlo. Tutto quello che stai facendo è creare una serie di dizionari denominata “sqlAndParams”, in questo array i dizionari di archiviazione con due chiavi “SQL” per l’istruzione sequel String o query e “PARAMS” che è solo una matrice di oggetti nativi SQLite capisce per quella domanda. Ogni “sqlParams” che è un singolo dizionario di sequel query più parametri viene quindi archiviato nell’array “sqlAndParams”. Una volta creato questo array, basta chiamare.

 ```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)") } ``` 

Inoltre, tutti i metodi executeStatement e getRecordsForQuery possono essere eseguiti con semplici stringhe per query SQL e una matrice per i parametri necessari alla query.

 ```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)") } ``` 

Esiste anche una versione Objective-C che viene chiamata la stessa SQLDataAccess, quindi ora puoi scegliere di scrivere il tuo sequel in Objective-C o Swift. Inoltre SQLDataAccess funzionerà anche con SQLCipher, il codice presente non è ancora configurato per funzionare con esso, ma è piuttosto facile da fare, e un esempio di come farlo è in realtà nella versione Objective-C di SQLDataAccess.

SQLDataAccess è una class molto veloce ed efficiente e può essere utilizzata al posto di CoreData che utilizza solo SQLite come archivio dati sottostante senza tutti i problemi di integrità dei dati core CoreData causati da CoreData.