2015-01-25 11 views
10

Przygotowałem szybki projekt, aby używać sqlite. czasami podczas wstawiania nie wstawia właściwie (lub wszystkich) wartości. Wiem, ponieważ ponownie uruchomiłem aplikację, a kiedy wrócę, wpisy są albo losowo błędne (z rzeczami, które nie zostały wstawione), albo zero. ale czasami poprawne.sqlite dla swift jest niestabilny

tutaj jest, gdzie ustawić, i tak dane są prawidłowe w wartościach przed wstawieniem.

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) 

widać wykomentowane println w środku, jeśli to nie jest komentarzem, wtedy itemName czasami dostaje część tego łańcucha.

Odpowiedz

14

Miałem ten sam problem. Znalazłem sposób na rozwiązanie tego problemu.

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

Powinieneś przekonwertować itemName jako NSString i użyć UTF8String do konwersji twojego ciągu na UTF8. Prawo kod jest taki sam tutaj

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

Powodzenia.

+0

Musisz również użyć 'SQLITE_TRANSIENT' dla ostatniego parametru do' sqlite3_bind_text' . – Rob

+0

SQLITE_TRANSIENT nie jest dostępny swift 3? Proszę, czy możesz mi doradzić. –

+0

@SaurabhPrajapati Znalazłem tę odpowiedź, która obejmuje ręczne definiowanie SQLITE_TRANSIENT w Swift 3: https://stackoverflow.com/a/26884081/470339 – Alastair

-1

To zachowanie faktycznie jest zgodne ze specyfikacją, a błąd znajduje się w kodzie.

Źródło problemu występuje w szybkim String przechodzeniu do sqlite3_bind_text. sqlite3_bind_text akceptuje tekst jako const char*, który jest mostkowany jako UnsafePointer<CChar> w Swift. Zachowanie podczas przechodzenia przez Swift String do funkcji akceptującej UnsafePointer<CChar> jest udokumentowane w sekcji "Stałe wskaźniki" w Interacting with C APIs. Jest napisane:

Ciąg zostanie automatycznie przekonwertowany na UTF8 w buforze, a wskaźnik do tego bufora zostanie przekazany do funkcji.

Prawdopodobnie to, co chcesz zrobić.

ALE jest napisane także:

przekazany do funkcji wskaźnik jest gwarancją ważna tylko na czas trwania wywołania funkcji. Nie próbuj utrzymywać wskaźnika i uzyskać do niego dostępu po powrocie funkcji.

To jest źródło Twojego błędu. sqlite3_bind_text() w rzeczywistości utrzymuje wskaźnik w przygotowanej instrukcji prawdopodobnie do momentu wywołania sqlite3_finalize(), dzięki czemu może go używać w przyszłych połączeniach sqlite3_step().

Kolejna odpowiedź sugerowana przy użyciu NSString.UTF8String. To życie trwa nieco dłużej i wydaje się, że powinno wystarczyć. documentation mówi:

Ta C ciąg jest wskaźnikiem do struktury wewnętrznej obiektu String, które mogą mieć krótszy niż czas życia obiektu strun i na pewno nie mają dłuższą żywotność. Dlatego powinieneś skopiować ciąg C, jeśli musi on być przechowywany poza kontekstem pamięci, w którym używasz tej właściwości.

"Kontekst pamięci" wydaje się niejasny. Nie jestem pewien, czy to oznacza bieżącą funkcję, czy do bieżącej autoreleasepool jest wyczerpany, lub coś innego. Jeśli jest to jedno z pierwszych dwóch, jesteś bezpieczny. Jeśli nie, dobrze byłoby powiedzieć, że nadal jesteś bezpieczny, ponieważ wydaje się, że w takich sytuacjach był przez długi czas bez problemów ..

Powiązane problemy