swift - custom - xcode navigation bar back button




如何在Swift中創建局部範圍? (4)

更新:在Swift 2.0中,您只需使用do關鍵字:

do {
    let label = UILabel()
    self.addSubview(label)
    self.titleLabel = label
}

對於Swift 2.0之前的情況也是如此:

您可以定義類似於此的內容:

func locally(@noescape work: () -> ()) {
    work()
}

然後使用如下的本地塊:

locally {
    let g = 42
    println(g)
}

(受到Scala的Predef對象的locally啟發。)

我經常在Objective-C中使用本地作用域來使命名更清晰。

{
    UILabel *label = [[UILabel alloc] init];
    [self addSubview:label];
    self.titleLabel = label;
}

我試圖在Swift中重寫這段代碼,如下所示:

{
    let label = UILabel()
    self.addSubview(label)
    self.titleLabel = label
}

這讓我得到以下錯誤:

Error: Braced block of statements is an unused closure.

那麼如何在Swift中創建局部範圍呢?


Swift 2開始 ,您可以使用do -statement創建本地範圍:

do {
    let x = 7
    print(x)
}
print(x) // error: use of unresolved identifier 'x'

然而,主要的用例似乎是使用do-try-catch進行錯誤處理 ,如“Swift編程語言”中的“錯誤處理”中所述,例如:

do {
    let jsonObj = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
    // success, do something with `jsonObj`...

} catch let error as NSError {
    // failure
    print("Invalid JSON data: \(error.localizedDescription)")
}

我所做的是定義一個匿名函數並執行它。

// ... preceding code ...
// ... might need semicolon here;
{
    () -> () in
    // ... this is a local scope ...
}()
// ... following code ...

你可能不得不在前一行的末尾添加一個分號,因此Swift認為這不是一個“尾隨閉包”。 您甚至可以將該分號放在開口花括號之前的同一行中。 所以,實現OP的原始代碼:

;{
    () -> () in
    let label = UILabel()
    self.addSubview(label)
    self.titleLabel = label
}()

編輯隨後, if true {...}我發現自己會重新開始。 正如Martin指出的那樣,在Swift 2中,允許do {...}作為定義任意範圍的官方方式,從而很好地解決了問題。


正如評論中所述,C中的匿名嵌套作用域通常表明您可以編寫更好的代碼。 例如,不是簡單地在最終設置self.titleLabel的嵌套作用域中進行工作,而是可以將該賦值作為評估內聯閉包的結果:

self.titleLabel = {
    let label = UILabel()
    label.text = "some text"
    // ... set other properties ...
    self.addSubview(label)
    return label
}()

這不僅將label保持為一個很好的短名稱,它僅限於創建和配置一個代碼塊的代碼塊,而是保留與為其創建值的屬性相關聯的代碼塊。 而且它更模塊化,因為你可以用一些其他標籤創建函數來替換整個閉包,如果它有助於分解代碼。

如果您發現自己經常這樣做,可以嘗試製作一個通用函數,讓您可以將構建代碼剪切為:

self.titleLabel = makeSubview(UILabel()) { label in
    label.text = "some text"
    // other label properties
}

但是我會把這樣的功能定義為讀者的練習。 ;)

正如Jean-Philippe Pellet的回答所述 ,在Swift 2.0及更高版本中, do構造是語言提供的明確方式。 (對於仍在使用Swift 1.x的人來說,他建議的基於功能的解決方案是一個不錯的選擇。)

另一個Swift 1.x解決方案 - 沒有定義新函數 - 是(顯式地)丟棄立即執行的閉包的結果:

 _ = {
     print("foo")
 }() 




swift