2015-01-25 11 views
10

Ho impostato il progetto rapido per usare sqlite. a volte, quando si inserisce in realtà non inserisce i valori corretti (o tutti). Lo so perché riavvio l'app, e quando torno nelle voci sono o casualmente sbagliato (con roba non inserita) o nullo. ma a volte corretto.sqlite per swift è instabile

qui è dove l'ho impostato e sì i dati sono corretti nei valori prima dell'inserimento.

let update = "INSERT INTO ToDoItem (itemName, completed, goalDate) " + "VALUES (?, ?, ?);" 
var statement: COpaquePointer = nil 
if sqlite3_prepare_v2(database, update, -1, &statement, nil) == SQLITE_OK { 
    let itemName = item.itemName as String 
    let completed = item.completed == true ? 1 : 0 

    sqlite3_bind_text(statement, 1, itemName, -1, nil) 
    sqlite3_bind_int(statement, 2, Int32(completed)) 

    if let goalDate = item.goalDate?.toString() { 
     sqlite3_bind_text(statement, 3, goalDate, -1, nil) 
    } else { 
     sqlite3_bind_text(statement, 3, "", -1, nil) 
    } 

    //println("inserting \(itemName), \(completed) and \(item.goalDate?.toString())") 
    //println("") 
} 

if sqlite3_step(statement) != SQLITE_DONE { 
    println("error updateing table") 
    sqlite3_close(database) 
    return 
} 
sqlite3_finalize(statement) 

sqlite3_close(database) 

si può vedere il println commentata in mezzo, se questo non è commentata, poi l'itemName volte diventa parte di quella stringa.

risposta

14

Ho avuto lo stesso problema. Ho trovato il modo di risolvere questo problema.

sqlite3_bind_text(statement, 1, itemName, -1, nil) --> itemName should be UTF8 String 

Si dovrebbe convertire itemName come NSString e utilizzare UTF8String per convertire la stringa a UTF8. codice giusto è lo stesso qui

let itemName = item.itemName as NSString 
sqlite3_bind_text(statement, 1, itemName.UTF8String, -1, nil) 

Buona fortuna.

+0

Devi anche usare 'SQLITE_TRANSIENT' per l'ultimo parametro per' sqlite3_bind_text' . – Rob

+0

SQLITE_TRANSIENT non è disponibile swift 3? puoi per favore avvisare –

+0

@SaurabhPrajapati Ho trovato questa risposta che copre la definizione manuale di SQLITE_TRANSIENT in Swift 3: https://stackoverflow.com/a/26884081/470339 – Alastair

-1

Questo comportamento in realtà è conforme alle specifiche e il bug è nel codice.

La fonte del problema si trova nello String rapido che si sta passando a sqlite3_bind_text. sqlite3_bind_text accetta il testo come const char* che viene risolto come UnsafePointer<CChar> in Swift. Il comportamento durante il passaggio di uno Swift String a una funzione che accetta UnsafePointer<CChar> è documentato nella sezione "Puntatori costanti" di Interacting with C APIs. Dice:

La stringa verrà automaticamente convertita in UTF8 in un buffer e un puntatore a tale buffer viene passato alla funzione.

Quale è probabilmente ciò che si desidera che accada.

MA si dice anche:

Il puntatore passato alla funzione è garantito per essere valida solo per la durata della chiamata di funzione. Non cercare di mantenere il puntatore e accedervi dopo che la funzione è tornata.

Questa è la fonte del bug. sqlite3_bind_text() infatti mantiene il puntatore nell'istruzione preparata probabilmente fino a quando non viene chiamato sqlite3_finalize() in modo che possa essere utilizzato nelle chiamate future sqlite3_step().

Un'altra risposta suggerita utilizzando NSString.UTF8String. Questo ha una vita che è un po 'più lunga e sembra che dovrebbe essere abbastanza. Il documentation dice:

Questa stringa C è un puntatore ad una struttura all'interno dell'oggetto stringa, che può avere una vita più breve rispetto all'oggetto stringa e certamente non hanno una vita più lunga. Pertanto, è necessario copiare la stringa C se deve essere memorizzata al di fuori del contesto di memoria in cui si utilizza questa proprietà.

"contesto di memoria" qui sembra vago. Non sono sicuro se significhi la funzione corrente, o fino a quando l'attuale autoreleasepool è esaurito, o qualcos'altro. Se è uno dei primi due, sei al sicuro. In caso contrario, direi che sei ancora al sicuro perché sembra che NSString.UTF8String sia stato utilizzato in situazioni come queste per lungo tempo senza problemi ..

Problemi correlati