我经常使用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中创建局部范围?
答案 0 :(得分:72)
更新:在Swift 2.0中,您只需使用do
关键字:
do {
let label = UILabel()
self.addSubview(label)
self.titleLabel = label
}
对于Swift pre-2.0来说这是真的:
您可以定义与此类似的内容:
func locally(@noescape work: () -> ()) {
work()
}
然后使用如下的locally
块:
locally {
let g = 42
println(g)
}
(灵感来自Scala的 Predef 对象中的locally
。)
答案 1 :(得分:6)
我认为不可能。
iBooks商店中至少有一本书中的语法没有提到它。
你可以这样做,
if (true) {
let a = 4
}
但我认为,这是一种不好的做法。
答案 2 :(得分:3)
从 Swift 2 开始,您可以使用do
语句创建一个本地范围:
do {
let x = 7
print(x)
}
print(x) // error: use of unresolved identifier 'x'
然而,主要的用例似乎是使用do-try-catch进行错误处理, 如"Error Handling"中所述 在"The Swift Programming Language"中,例如:
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)")
}
答案 3 :(得分:2)
如评论中所述,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's answer中所述,在Swift 2.0及更高版本中,do
构造是显式语言提供的方法。 (对于仍在使用Swift 1.x的人来说,他建议的基于功能的解决方案是一个不错的选择。)
另一个Swift 1.x解决方案 - 没有定义新函数 - 是(显式地)抛弃立即执行的闭包的结果:
_ = {
print("foo")
}()
答案 4 :(得分:-1)
我所做的是定义一个匿名函数并执行它。
// ... 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 {...}
将被允许作为定义任意范围的官方方式,从而很好地解决了这个问题。