将sqlite3_exec回调函数的结果保存到Swift中的字典中

时间:2019-06-04 12:38:36

标签: ios swift sqlite closures

我想创建一个函数,该函数执行sqlite3_exec并将结果保存到作为参数传递的字典对象中。为此,我创建了以下代码:

func execute(sql: String, result: inout Dictionary<String, String>) {
    let rc = sqlite3_exec(
        dbPointer,      // database
        sql, // statement
        {        // callback: non-capturing closure
            resultVoidPointer, columnCount, values, columns in

            for i in 0 ..< Int(columnCount) {
                let value = String(cString: values![i]!)
                let column = String(cString: columns![i]!)
                result[column] = value         // Error: Escaping closures can only capture inout parameters explicitly by value
                print("\(column) = \(value)")
            }
            return 0
    },
        nil,
        nil
    )

    if rc != SQLITE_OK {
        print("SQLite Error: " + errorMessage)
    }
}

但是此代码给了我以下错误:Escaping closures can only capture inout parameters explicitly by value。另一个尝试是使函数execute返回字典对象,但是错误消息变为:A C function pointer cannot be formed from a closure that captures context。我该如何解决?

1 个答案:

答案 0 :(得分:0)

Shawn的评论之后,我创建了execute的新版本,在这里我使用sqlite3_prepare_v2sqlite3_stepsqlite3_finalize而不是组合函数sqlite3_exec

func prepare(sql: String) -> OpaquePointer? {
    var statement: OpaquePointer? = nil
    guard sqlite3_prepare_v2(dbPointer, sql, -1, &statement, nil) == SQLITE_OK else {
        print(errorMessage)
        return nil
    }
    return statement
}


func execute(sql: String) -> [Dictionary<String, String>] {
    var result: [Dictionary<String, String>] = []

    guard let queryStatement = prepare(sql: sql) else {
        return result
    }

    defer {
        sqlite3_finalize(queryStatement)
    }

    while sqlite3_step(queryStatement) == SQLITE_ROW {
        var dictionary: Dictionary<String, String> = [:]

        for i in 0...sqlite3_column_count(queryStatement)-1 {
            let column: String = String(cString: sqlite3_column_name(queryStatement, i))
            let value: String = String(cString: sqlite3_column_text(queryStatement, i))
            dictionary[column] = value
        }

        result.append(dictionary)
    }

    guard sqlite3_step(queryStatement) == SQLITE_DONE else {
        print(errorMessage)
        return result
    }

    return result
}

我的execute函数现在返回一个字典数组,其中每个字典代表SQL语句(如SELECT)的一行。对于诸如INSERT,UPDATE或DELETE之类的其他SQL语句,其中将不返回任何行,该函数execute返回一个空数组。

执行SQL语句后,可以通过

访问结果
let result = execute(db, "SELECT id, name, age FROM Table")
print(result[i][age])      // prints the value in row i and column age