1

我正在开发一个使用 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)

    }
}
4

1 回答 1

2

几点观察:

  1. 有了sqlite3_bind_blob,第四个参数是大小,是必填项,不能为负数。使用sqlite3_bind_text,您可以提供一个-1值,因为 C 字符串是空终止的,并且它可以确定字符串的结束位置,但它不能用 blob 做到这一点。

    正如文档所说:

    如果第四个参数 tosqlite3_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 返回码时,您都应该这样做。这通常会使诊断呼叫失败的原因变得更加容易。

于 2020-10-16T13:01:22.067 回答