在 Swift 中将数据保存到 sqlite3 数据库中
Saving data into sqlite3 database in Swift
我正在开发一个使用 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)
}
}
几点观察:
和sqlite3_bind_blob
一样,第四个参数是大小,必填,不能为负数。使用 sqlite3_bind_text
,您可以提供一个 -1
值,因为 C 字符串以 null 结尾,它可以找出字符串的结尾位置,但它不能用 blob 做到这一点。
正如the documentation所说:
If the fourth parameter to sqlite3_bind_blob()
is negative, then the behavior is undefined.
因此,也许:
guard let blob = drawingBuffer.baseAddress else { return }
let count = Int32(drawingBuffer.count)
然后:
sqlite3_bind_blob(statement, 1, blob, count, nil)
此外,如果 SQLite 调用失败,你应该打印错误,否则你就瞎了,例如
let errorMessage = sqlite3_errmsg(database).map { String(cString: [=12=]) } ?? "Unknown error"
print("failure preparing UPDATE statement: \(errorMessage)")
无论何时检查 SQLite return 代码,都应该这样做。通常这将使诊断呼叫失败的原因变得更加容易。
我正在开发一个使用 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)
}
}
几点观察:
和
sqlite3_bind_blob
一样,第四个参数是大小,必填,不能为负数。使用sqlite3_bind_text
,您可以提供一个-1
值,因为 C 字符串以 null 结尾,它可以找出字符串的结尾位置,但它不能用 blob 做到这一点。正如the documentation所说:
If the fourth parameter to
sqlite3_bind_blob()
is negative, then the behavior is undefined.因此,也许:
guard let blob = drawingBuffer.baseAddress else { return } let count = Int32(drawingBuffer.count)
然后:
sqlite3_bind_blob(statement, 1, blob, count, nil)
此外,如果 SQLite 调用失败,你应该打印错误,否则你就瞎了,例如
let errorMessage = sqlite3_errmsg(database).map { String(cString: [=12=]) } ?? "Unknown error" print("failure preparing UPDATE statement: \(errorMessage)")
无论何时检查 SQLite return 代码,都应该这样做。通常这将使诊断呼叫失败的原因变得更加容易。