我刚看到Apple的示例代码:
let timeRemainingFormatter: NSDateComponentsFormatter = {
let formatter = NSDateComponentsFormatter()
formatter.zeroFormattingBehavior = .Pad
formatter.allowedUnits = [.Minute, .Second]
return formatter
}()
var timeRemainingString: String {
let components = NSDateComponents()
components.second = Int(max(0.0, timeRemaining))
return timeRemainingFormatter.stringFromDateComponents(components)!
}
问题是:常量和变量都是用闭包声明的,但是一个具有等号,另一个不是。为什么呢?
答案 0 :(得分:2)
()
说“立即执行并返回结果。”现在回答一个冗长的答案:
let timeRemainingFormatter: NSDateComponentsFormatter = {
// ...
}() // <- The '()' means "execute now and give me the formatter"
timeRemainingFormatter
将在初始时计算一次,并且将存储该值。括号表示应立即执行闭包并返回结果,在这种情况下将存储为属性。
var timeRemainingString: String {
// ...
}
每次调用时都会计算 timeRemainingString
。
更一般地说,在Swift中,函数只是命名闭包。定义如下函数:
func myFunc() -> Void {
print("Function")
}
与定义闭包几乎相同:
let myClosure: () -> Void = {
print("Closure")
}
在这两种情况下,您都有一个名称(myFunc
/ myClosure
),一个呼叫签名(() -> Void
)和一个代码块({ print(...) }
)。< / p>
就像你打电话给你的职能一样:
myFunc()
您可以调用存储的闭包,例如:
myClosure()
两者都会打印出来。
函数几乎只是定义命名闭包的便利。
假设您有一个全局函数和一个全局存储闭包,分别定义为:
func myIntFunc() -> Int { return 1 }
let myIntClosure: () -> Int = { return 2 }
相似之处应该非常明显。
现在,您希望在类中将它们用作属性。你做了
class MyClass {
let funcInt: Int = myIntFunc() // would resolve to 1
let closureInt: Int = myIntClosure() // would resolve to 2
}
注意在这两者结尾处()
的方式。这说“执行我的函数/闭包以获得Int
。”
现在假设您不想定义全局闭包;你宁愿把这些代码放在你的课堂上,以保持井井有条。所以你这样做:
class MyClass {
let funcInt: Int = myIntFunc() // would resolve to 1
let closureInt: Int = { return 2 }() // would resolve to 2
}
你仍然需要执行你的闭包来获取Int
,就像函数一样。所以你把()
放在它之后,就像函数一样。
最后,我们将触及“计算属性”。
var timeRemainingString: String {
// ...
}
您可以将此视为编写不带参数的函数的一种方式,因此您可以获得一个快捷的调用签名(您可以将其视为属性)。它实际上就像是由属性存储闭包,但因为它是一种特殊的符号,Swift知道执行闭包并在每次调用属性时返回其结果。因此,这是一个“计算属性”。
致电时:
let timeRemaining = instance.timeRemainingString
斯威夫特真的把它翻译成:
let timeRemaining = instance.timeRemainingString()
它只是为您添加()
以使存储的闭包执行。