2017-09-07 3 views
0

développeur expérimenté ici ... mais un peu nouveau à Swift et débutant défini avec SQLite.swift ...simple magasin/récupération de données blob ou (NSKeyArchive d'une classe peut-être)

Je suis en train de mettre la main autour de l'utilisation de SQLite dans une application iOS - j'ai donc créé une application simple pour m'assurer d'avoir les bases ... Tout se passait bien jusqu'à ce que je récupère et récupère des objets de données (objets de classe) ...

Voici mon code:

//********************************************************************** 
    //** 
    //** Create/Open database connection 
    //** 
    //********************************************************************** 
    let dbPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! 
    let db: Connection = try! Connection("\(dbPath)/stickis.sqlite3") 

    let dbTable = Table("testtbl") 
    let id = Expression<Int64>("id") 
    let boolfld = Expression<Bool>("boolfld") 
    let int64fld = Expression<Int64>("int64fld") 
    let stringfld = Expression<String>("stringfld") 
    let blobfld = Expression<SQLite.Blob?>("blobfld") // optional due to ? 

    //********************************************************************** 
    //* 
    //* Drop table if it exists 
    //* 
    //********************************************************************** 
    try! db.run(dbTable.drop(ifExists: true)) 

    //********************************************************************** 
    //** 
    //** Create/Open Table 
    //** 
    //********************************************************************** 
    do 
    { 
     try db.run((dbTable.create(ifNotExists: true) 
     { 
      t in 
      t.column(id, primaryKey: true) 
      t.column(boolfld) 
      t.column(int64fld) 
      t.column(stringfld) 
      t.column(blobfld) 
      }) 
     ) 
    } 
    catch 
    { 
     print("Failed to create sticki table") 
    } 

    //********************************************************************** 
    //** 
    //** Add Record 1 
    //** 
    //********************************************************************** 
    do 
    { 
     let testblob: Blob = windowcontent() 
     let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1963, stringfld <- "unknown", blobfld <- testblob)) 
     print("inserted id: \(rowid)") 
    } 
    catch 
    { 
     print("insertion failed: \(error)") 
    } 

    //********************************************************************** 
    //** 
    //** Add Record 2 
    //** 
    //********************************************************************** 
    do 
    { 
     let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1972, stringfld <- "David")) 
     print("inserted id: \(rowid)") 
    } 
    catch 
    { 
     print("insertion failed: \(error)") 
    } 

    //********************************************************************** 
    //** 
    //** Update Record 1 
    //** 
    //********************************************************************** 
    let rec2updt = dbTable.filter(id == 1) 
    do 
    { 
     if try db.run(rec2updt.update(stringfld <- "TJ")) > 0 
     { 
      print("updated to TJ") 
     } 
     else 
     { 
      print("record not found") 
     } 
    } 
    catch 
    { 
     print("update failed") 
    } 

    //********************************************************************** 
    //** 
    //** Query Particular Record using filter 
    //** 
    //********************************************************************** 
    let tjFilter = dbTable.filter(int64fld == 1964) 
    for dataRec in try! db.prepare(tjFilter) 
    { 
     print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])") 
    } 

    //********************************************************************** 
    //** 
    //** Query All Records 
    //** 
    //********************************************************************** 
    for dataRec in try! db.prepare(dbTable) 
    { 
     print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])") 
    } 

    //********************************************************************** 
    //** 
    //** Delete Records 
    //** 
    //********************************************************************** 
    try! db.run(dbTable.delete()) 

Tout fonctionnait très bien f ou moi .... jusqu'à ce que j'ajouté la ligne suivante sous la « Ajouter un enregistrement 1 » bloc de commentaire ...

let testblob: Blob = windowcontent() 

contenuFenêtre() est une classe (ou pourrait être un struct) que je veux « Archive "et enregistrer ... La raison pour laquelle j'utilise un Blob pour le stocker est que le type d'objet stocké pourrait être de plusieurs classes différentes.

J'ai aussi essayé ceci:

 let testdata: Data = Data() 
     let testblob: Blob = testdata as Blob 

et obtenir une erreur attendue de l'impossibilité de convertir les données à Blob

Quelqu'un at-il un exemple simple d'attribution et la récupération de données vers/depuis un SQLite.Blob qu'ils partageraient avec moi?

Aussi, côté sujet, y a-t-il un bon endroit où je peux partager mon code d'exemple iOS "de base" une fois que je l'ai tout en cours d'exécution? En supposant que d'autres débutants peuvent venir et cela pourrait rendre leur vie plus facile.

+0

Pour votre information ... Je ne pensais pas « laisser testblob: Blob = contenuFenêtre() » pour travailler en fait ... c'était la meilleure façon pour moi de montrer simplement ce que je voulais code ... si s'il vous plaît ne pas être pris en charge en essayant de déboguer la syntaxe de cette ligne ... – tj4shee

+0

Figuré sur une partie de la solution .... utiliser Blob (octets: [UInt8] (xxx)) pour convertir les données dans le blob. .. où xxx est l'objet de données .... Maintenant, pour comprendre comment convertir en données ... – tj4shee

+0

La 2ème partie de la solution - la conversion du Blob en données est faite en utilisant Blob.bytes ... voir le code que j'entre en réponse. – tj4shee

Répondre

0

Voici le code qui répond à ma question. Voir la section "Interroger un enregistrement particulier en utilisant un filtre" pour savoir où je convertis Blob en String.

override func viewDidLoad() 
{ 
    super.viewDidLoad() 
    // Do any additional setup after loading the view. 


    //********************************************************************** 
    //** 
    //** Create/Open database connection 
    //** 
    //********************************************************************** 

    // dbpath is where we want the sqlite file to reside... in this case we are using the documents directory 
    let dbPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! 

    // the filename we are giving our database is "testdb.sqlite3" - it can be what ever you like. If the file exists, it opens it as a database, if it does not exist, it will create it and then open it. 
    let db: Connection = try! Connection("\(dbPath)/testdb.sqlite3") 

    // defining the name of the SQLite table we want to use as well as the field names we want to create in the table. In this case, we are creating one of each major type of fields - Bool, Long Int, String, Blob 
    let dbTable = Table("testtbl") 
    let id = Expression<Int64>("id") 
    let boolfld = Expression<Bool>("boolfld") 
    let int64fld = Expression<Int64>("int64fld") 
    let stringfld = Expression<String>("stringfld") 
    let blobfld = Expression<SQLite.Blob?>("blobfld") // Blob field is optional due to SQLite.Blob? - remove the ? to make it require "Not Null" 

    //********************************************************************** 
    //* 
    //* Drop table if it exists 
    //* 
    //********************************************************************** 
    // Deleting the table if it exists - this is simply to allow the program to be rerun and start by creating a new table 
    try! db.run(dbTable.drop(ifExists: true)) 

    //********************************************************************** 
    //** 
    //** Create/Open Table 
    //** 
    //********************************************************************** 
    do 
    { 
     // create the table with the following fields... 
     try db.run((dbTable.create(ifNotExists: true) 
     { 
      t in 
      // the fields in our table... 
      t.column(id, primaryKey: true) 
      t.column(boolfld) 
      t.column(int64fld) 
      t.column(stringfld) 
      t.column(blobfld) 
      }) 
     ) 
    } 
    catch 
    { 
     // should not get to this, but if it does, you can expect the remainder of the app to fail also. 
     print("Failed to create sticki table") 
    } 

    //********************************************************************** 
    //** 
    //** Add Record 1 
    //** 
    //********************************************************************** 
    do 
    { 
     // setup a Data var and then save it as an SQLite.Blob 
     let testdata: Data = "foo".data(using: .utf8)! //Data() 
     let testblob: Blob = Blob(bytes: [UInt8](testdata)) 

     // insert a new record into the database... the function will return the rowID of the newly inserted record. 
     let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1963, stringfld <- "unknown", blobfld <- testblob)) 

     print("inserted id: \(rowid)") 
    } 
    catch 
    { 
     print("insertion failed: \(error)") 
    } 

    //********************************************************************** 
    //** 
    //** Add Record 2 
    //** 
    //********************************************************************** 
    do 
    { 
     // Adding a 2nd record to the database - no Blob field this time 
     let rowid = try db.run(dbTable.insert(boolfld <- true, int64fld <- 1972, stringfld <- "David")) 
     print("inserted id: \(rowid)") 
    } 
    catch 
    { 
     print("insertion failed: \(error)") 
    } 

    //********************************************************************** 
    //** 
    //** Update Record 1 
    //** 
    //********************************************************************** 

    // Setup filter to get record "WHERE id == 1" 
    let rec2updt = dbTable.filter(id == 1) 
    do 
    { 
     // db.run will return the # of records updated - must be > 0 (actually, == 1) 
     if try db.run(rec2updt.update(stringfld <- "TJ")) > 0 
     { 
      print("updated to TJ") 
     } 
     else 
     { 
      print("record not found") 
     } 
    } 
    catch 
    { 
     print("update failed") 
    } 

    //********************************************************************** 
    //** 
    //** Query Particular Record using filter 
    //** 
    //********************************************************************** 

    // Setup filter to get record "WHERE int64fld == 1963" 
    let tjFilter = dbTable.filter(int64fld == 1963) 

    // Run using filter and print out results (should only be 1 rec in our case) 
    for dataRec in try! db.prepare(tjFilter) 
    { 
     // Convert Blob back to String 
     let tmpStr: String = String(bytes: dataRec[blobfld]!.bytes, encoding: .utf8)! 
     print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld]), blobfld: \(tmpStr)") 
    } 

    //********************************************************************** 
    //** 
    //** Query All Records 
    //** 
    //********************************************************************** 

    // Prints all records in database 
    for dataRec in try! db.prepare(dbTable) 
    { 
     print("id: \(dataRec[id]), stringfld: \(dataRec[stringfld])") 
    } 

    //********************************************************************** 
    //** 
    //** Delete Records 
    //** 
    //********************************************************************** 

    // Deletes ALL records in the table (use a filter to delete individual records) 
    try! db.run(dbTable.delete()) 

} 

override func didReceiveMemoryWarning() 
{ 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
}