Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 用于swift的sqlite不稳定_Ios_Sqlite_Swift - Fatal编程技术网

Ios 用于swift的sqlite不稳定

Ios 用于swift的sqlite不稳定,ios,sqlite,swift,Ios,Sqlite,Swift,我已经建立了使用sqlite的swift项目。有时,当插入时,它实际上并没有插入正确(或全部)的值。我知道,因为我重新启动了应用程序,当我返回时,条目要么是随机错误(没有插入内容),要么是零。但有时是正确的 这里是我设置它的地方,是的,插入之前的值中的数据是正确的 let update = "INSERT INTO ToDoItem (itemName, completed, goalDate) " + "VALUES (?, ?, ?);" var statement: COpaquePoin

我已经建立了使用sqlite的swift项目。有时,当插入时,它实际上并没有插入正确(或全部)的值。我知道,因为我重新启动了应用程序,当我返回时,条目要么是随机错误(没有插入内容),要么是零。但有时是正确的

这里是我设置它的地方,是的,插入之前的值中的数据是正确的

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)

中间可以看到注释的打印,如果没有注释,那么ItNeNm有时会得到该字符串的一部分。

我也遇到了同样的问题。我找到了解决这个问题的方法

sqlite3_bind_text(statement, 1, itemName, -1, nil) --> itemName should be UTF8 String
您应该将
itemName
转换为
NSString
,并使用
UTF8String
将字符串转换为
UTF8
。正确的代码在这里是相同的

让itemName=item.itemName作为NSString
sqlite3_bind_text(语句,1,itemName.UTF8String,-1,nil)

祝你好运。

这种行为实际上符合规范,错误就在你的代码中

问题的根源在于您要传递给
sqlite3\u bind\u text
的swift
字符串中
sqlite3\u bind\u text
接受作为
const char*
的文本,该文本在Swift中桥接为
UnsafePointer
。将Swift
字符串
传递给接受
UnsafePointer
的函数时的行为记录在。它说:

字符串将在缓冲区中自动转换为UTF8,并将指向该缓冲区的指针传递给函数

这可能就是你想要发生的

但它也说:

传递给函数的指针保证仅在函数调用期间有效。不要试图持久化指针并在函数返回后访问它

这就是你的bug的来源
sqlite3\u bind\u text()
实际上可能会在调用
sqlite3\u finalize()
之前将指针保留在准备好的语句中,以便它在以后的
sqlite3\u step()
调用中使用它

另一个答案建议使用
NSString.UTF8String
。这有一个较长的生命周期,似乎应该足够了。报告说:

这个C字符串是一个指向string对象内部结构的指针,它的生存期可能比string对象短,并且肯定不会有更长的生存期。因此,如果需要将C字符串存储在使用此属性的内存上下文之外,则应复制该字符串


这里的“记忆语境”似乎很模糊。我不确定这是否意味着当前函数,或者直到当前自动释放池耗尽,或者其他什么。如果是前两个中的一个,你就安全了。如果不是,我会说你仍然安全,因为它看起来像是
NSString.UTF8String
已经在这种情况下使用了很长时间,没有任何问题。

在swift中,SQLite没有定义
SQLite\u TRANSIENT
SQLite\u STATIC
,所以我们需要明确定义它

swift 3&4

定义SQLITE的以下属性

let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
SQL函数 在绑定文本时添加
SQLITE\u TRANSIENT
而不是
nil
作为最后一个参数
sqlite3\u bind\u text

let update = "INSERT INTO ToDoItem (itemName, completed, goalDate) " + "VALUES (?, ?, ?);"
var statement: OpaquePointer = 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, SQLITE_TRANSIENT)
    sqlite3_bind_int(statement, 2, Int32(completed))

    if let goalDate = item.goalDate?.toString() {
        sqlite3_bind_text(statement, 3, goalDate, -1, SQLITE_TRANSIENT)
    } else {
        sqlite3_bind_text(statement, 3, "", -1, SQLITE_TRANSIENT)
    }

    //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)
引用自


您还必须使用
SQLITE\u TRANSIENT
作为
sqlite3\u bind\u text
的最后一个参数。SQLITE\u TRANSIENT不可用吗?请您提供建议。@SaurabhPrajapati我在Swift 3中找到了这个包含手动定义SQLITE_瞬态的答案:这应该是可以接受的答案