如何在Swift中创build局部范围?

我经常在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中创build一个本地作用域?

更新:在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启发。)

我不认为这是可能的。

至less在iBooks商店中可用的书中的语法没有提及它。

你可以做到这一点,

 if (true) { let a = 4 } 

但我认为,这是一个不好的做法。

Swift 2开始 ,可以使用do -statement创build一个本地范围:

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

但是,主要用例似乎是do-try-catch的error handling ,如“Swift编程语言”中的“error handling”中所述,例如:

 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)") } 

正如评论中指出的那样,C语言中的匿名嵌套作用域通常表示您可以编写更好的代码。 例如,不是简单地在最终设置self.titleLabel的嵌套作用域中进行工作,而是可以将该作业作为评估内联closures的结果:

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

这不仅将label保持为一个很好的简短名称,它仅限于创build和configuration一个代码块的代码块,而是保持与创build它的值的属性相关联的代码块。 而且它更加模块化,因为你可以用一个其他标签创build函数来replace整个闭包,如果它有用于分解代码。

如果你经常发现自己在做这样的事情,你可以尝试制作一个通用的函数,让你把你的构造代码降低到这个:

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

但是我会留下这样一个function来作为读者的练习。 ;)


正如Jean-Philippe Pellet的回答中所指出的那样,在Swift 2.0和之后的版本中, do构造是明确的语言提供的方式。 (他build议基于function的解决scheme对于仍在使用Swift 1.x的人来说是一个不错的select)

另一个Swift 1.x解决scheme – 没有定义一个新的函数 – 是(明确地)抛弃立即执行的闭包的结果:

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

我所做的是定义一个匿名函数并执行它。

 // ... 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 {...}而不是。 正如马丁指出的那样,尽pipe在Swift 2中, do {...}将被允许​​作为定义任意范围的官方方式,从而很好地解决了这个问题。