Swift 在离开函数之前执行代码

Swift 在离开函数之前执行代码,swift,sqlite,Swift,Sqlite,我目前正在为sqlite数据库编写一些代码。我注意到,在准备查询之后,我总是需要在退出函数之前完成查询(sqlite3\u finalize(statementPointer))。除了填上所有的可能性,还有别的方法吗 例如: func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool { var statement = "UPDATE MY_TABLE S

我目前正在为
sqlite
数据库编写一些代码。我注意到,在准备查询之后,我总是需要在退出函数之前完成查询(
sqlite3\u finalize(statementPointer)
)。除了填上所有的可能性,还有别的方法吗

例如:

func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool {
    var statement = "UPDATE MY_TABLE SET X=?"
    var statementPointer: COpaquePointer = nil
    if y != nil {
        statement += ", Y=?"
    }
    statement += " WHERE NAME=?"
    if sqlite3_prepare_v2(db, statement, -1, &statementPointer, nil) != SQLITE_OK {
        return false
    } else if sqlite3_bind_int64(statementPointer, 1, x) != SQLITE_OK {
        // Note this code here
        sqlite3_finalize(statementPointer)
        return false
    }

    if y != nil {
        if sqlite3_bind_text(statementPointer, 2, y, -1, nil) != SQLITE_OK {
            // Note this repetition
            sqlite3_finalize(statementPointer)
            return false
        }
    }

    if sqlite3_step(statementPointer) != SQLITE_DONE {
        // Note this repetition
        sqlite3_finalize(statementPointer)
        return false
    }
    // Note this repetition
    sqlite3_finalize(statementPointer)
    return true
}
当然,这只是我用来说明这一点的。在真正的代码中,有许多其他的
if
子句需要我完成它们的语句

我知道swift中的类类似于
deinit
,但是函数也有
deinit
s吗

例如(我希望它像但不起作用的代码):

如何使用关键字

是的,有一个“函数的Denit”-它被称为:

defer
语句用于在将程序控制转移到出现
defer
语句的范围之外之前执行代码

请注意,与假设的示例不同,
defer
语句必须出现在任何可能导致其执行清理的事件之前,而不是在封闭范围的末尾。一般来说,它是这样工作的:

func doStuff() {
    let resource = acquireResource()
    defer {
        cleanup(resource)
    }
    if something { return }
    doOtherStuff()
}
func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool {
    var statementPointer: COpaquePointer = nil
    //... Other stuff...

    guard sqlite3_prepare_v2(db, statement, -1, &statementPointer, nil) == SQLITE_OK
        else { return false }
    // after this you want any possible exit to do finalize, so put the defer here
    defer { sqlite3_finalize(statementPointer) }

    // every `return` after here, true or false, will execute the `defer` clause
    guard sqlite3_bind_int64(statementPointer, 1, x) == SQLITE_OK 
        else { return false }

    guard y != nil && sqlite3_bind_text(statementPointer, 2, y, -1, nil) == SQLITE_OK 
        else { return false }

    guard sqlite3_step(statementPointer) == SQLITE_DONE 
        else { return false }

    return true
}
在这里,
cleanup(resource)
将被调用,而不管函数是否因为
if something
或因为它到达其作用域的末尾(在
doOtherStuff()之后)而退出

你不能像你所问的那样把一个
延迟
放在
if
里面——它只会延迟到它所在范围的出口,所以它会在
if
主体的末尾执行。但是,
defer
guard
配合得很好。。。在您的情况下,您可能需要以下内容:

func doStuff() {
    let resource = acquireResource()
    defer {
        cleanup(resource)
    }
    if something { return }
    doOtherStuff()
}
func updateColumn(db: COpaquePointer, name: String, x: sqlite3_int64, y: String!=nil) -> Bool {
    var statementPointer: COpaquePointer = nil
    //... Other stuff...

    guard sqlite3_prepare_v2(db, statement, -1, &statementPointer, nil) == SQLITE_OK
        else { return false }
    // after this you want any possible exit to do finalize, so put the defer here
    defer { sqlite3_finalize(statementPointer) }

    // every `return` after here, true or false, will execute the `defer` clause
    guard sqlite3_bind_int64(statementPointer, 1, x) == SQLITE_OK 
        else { return false }

    guard y != nil && sqlite3_bind_text(statementPointer, 2, y, -1, nil) == SQLITE_OK 
        else { return false }

    guard sqlite3_step(statementPointer) == SQLITE_DONE 
        else { return false }

    return true
}