在Swift中声明带闭包的变量之后何时使用等号

时间:2015-07-14 04:02:36

标签: swift

我刚看到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)!
}

问题是:常量和变量都是用闭包声明的,但是一个具有等号,另一个不是。为什么呢?

1 个答案:

答案 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()

它只是为您添加()以使存储的闭包执行。

事实上事情实际上有点复杂,因为你可以定义setter闭包以及我们刚才讨论的getter,甚至是观察者闭包。 Swift将根据您尝试执行的操作调度到正确的闭包。