2016-08-10 41 views
2

我目前正在编写一个sqlite数据库的代码。我注意到在准备查询之后,我总是需要在退出函数之前完成查询(sqlite3_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条款,我需要最终确定他们的陈述。

据我所知,这是类似于deinit类的swift,但有deinit s的功能呢?

例如(代码,我想它是这样,但不工作):

func updateColumn(params...) -> Bool { 
    // code... 
    deinit { 
     sqlite3_finalize(statementPointer) 
    } 
} 

回答

6

是的,有一个“DEINIT的功能” - 这就是所谓的defer

一个defer声明就转移出现的defer声明范围之外程序控制之前用于执行代码英寸

注意,不像你的假设的例子中,defer语句必须之前出现无论发生什么情况都会导致它执行的清理,而不是在封闭范围的末尾。在一般情况下,它的工作原理是这样的:

func doStuff() { 
    let resource = acquireResource() 
    defer { 
     cleanup(resource) 
    } 
    if something { return } 
    doOtherStuff() 
} 

这里,cleanup(resource)得到不论功能是否退出,因为if something调用,还是因为它达到其范围的结束(doOtherStuff()后)。

你不能把一个deferif里面就像你问 - 它只是推迟到它在范围内的出口,所以它会在if体结束执行。但defer确实与guard配搭得很好......在你的情况下,你可能想要这样的东西:

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 
} 
0

怎么样使用defer关键字。

func updateColumn(params...) -> Bool { 
    // code... 
    defer { 
     sqlite3_finalize(statementPointer) 
    } 
} 
相关问题