将数据保存到Swift中的sqlite3数据库中



我正在开发一个使用PencilKit的应用程序。我试图将PK图形以数据的形式保存在sqlite3数据库中,但没有保存。我认为问题出在保存功能上,而不是获取要显示的图形数据的功能上,因为当我直接在终端中查询时,数据库中的图形行是空的。

func save(canvas: Canvas) {
// connect to database
connect()

// canvas.drawing is already in the form of data not PK drawing here
let drawingData = canvas.drawing

drawingData.withUnsafeBytes { drawingBuffer in

let drawingPtr = drawingBuffer.baseAddress!
var statement: OpaquePointer!

if sqlite3_prepare_v2(database, "UPDATE drawings SET drawing = ? WHERE rowid = ?", -1, &statement, nil) != SQLITE_OK {
print("Could not create (update) query")
}

sqlite3_bind_blob(statement, 1, drawingPtr, -1, nil)
sqlite3_bind_int(statement, 2, Int32(canvas.id))

if sqlite3_step(statement) != SQLITE_DONE {
print("Could not execute update statement")
}

sqlite3_finalize(statement)
}
}

一些观察结果:

  1. 对于sqlite3_bind_blob,第四个参数是大小,这是必需的,并且不能为负数。使用sqlite3_bind_text,您可以提供-1值,因为C字符串是以null结尾的,它可以确定字符串的结尾位置,但使用blob无法做到这一点。

    正如文件所说:

    如果sqlite3_bind_blob()的第四个参数为负,则行为未定义。

    因此,也许:

    guard let blob = drawingBuffer.baseAddress else { return }
    let count = Int32(drawingBuffer.count)
    

    然后:

    sqlite3_bind_blob(statement, 1, blob, count, nil)
    
  2. 此外,如果SQLite调用失败,您应该打印错误,否则您就是盲目的,例如

    let errorMessage = sqlite3_errmsg(database).map { String(cString: $0) } ?? "Unknown error"
    print("failure preparing UPDATE statement: (errorMessage)")
    

    无论何时检查SQLite返回代码,都应该这样做。通常,这将使诊断呼叫失败的原因变得更加容易。

最新更新