NumberFormatter 只能写在闭包中

NumberFormatter can only be written in closure

在阅读 The Big Nerd Ranch Guide 一书时,我在其中一章中看到一段话,要求您创建 NumberFormatter 的实例。一切都按预期工作,但我注意到格式化程序是使用 closure 创建的:

class ConversionViewController: UIViewController {
    let numberFormatter: NumberFormatter = {
        let nf = NumberFormatter()

        nf.numberStyle = .decimal
        nf.minimumFractionDigits = 0
        nf.maximumFractionDigits = 1

        return nf
    }()

    func updateCelsiusLabel() {
        if let celsiusValue = celsiusValue {
             celsiusLabel.text = numberFormatter.string(from: NSNumber(value: celsiusValue.value))
        } else {
            celsiusLabel.text = "???"
        }
    }
}

出于好奇,我尝试在闭包之外创建此格式化程序,例如:

let nf = NumberFormatter()

nf.numberStyle = .decimal
nf.minimumFractionDigits = 0
nf.maximumFractionDigits = 1

但是收到错误提示

Expected declaration

我的问题是:

  1. 为什么不能 NumberFormatters 在闭包外创建 案例?
  2. 括号()末尾代表什么 关闭?我的猜测是它是自调用的,但为什么需要这样呢?

到目前为止,我从未见过以这种方式编写的闭包。 Apple 文档中有什么解释这个的吗?

NumberFormatter 以及闭包实例化在这里是一个转移注意力的问题:问题是您试图直接在 属性 (nf)类型声明的范围(尽管您未能向我们展示您的所有代码确实包含在类型定义的范围内),但超出了例如实例函数或初始化器。

比较:

struct Foo {
    var a = 1
    a = 2 // Error: expected declaration
}

一个编译示例是:

struct Foo {
    var a = 1
    mutating func mutateMe() {
        a = 2 // OK
    }
}

至于你的问题 2):括号 () 用于执行闭包的一次调用,其中 return闭包用于实例化nf。如果您没有调用它,那么 nf 将是类型 () -> NumberFormatter 的闭包,而不是 NumberFormatter 的实际实例。比较:

struct Foo {
    let a: Int = { 
        var a = 1
        a = 2
        return a
    }() // instantiate 'a' of Foo by _once-only 
        // invoking a specified closure_.
}

与相同概念但在类型之外进行比较 declaration/definition:

// this is a closure
let aClosure: () -> Int = { _ in return 42 }

// this is an invokation of a closure
// (discarding the result)
_ = aClosure()

// this is also an invokation of a closure
let num = { _ in return 42 }() // 'num' inferred to Int

nf 在这种情况下是一个实例 属性。它本身就是一个 class 拥有自己的 属性。当你声明

let nf = NumberFormatter()

nf 适合您,但具有默认属性。而且你不能在声明中设置它的 属性 。你会得到这个错误。

第一个答案: 我在 Playground 中测试了您的代码片段,它没有显示任何错误。我认为你可能做错了与 NumberFormatter.

无关的事情
let nf = NumberFormatter()
nf.numberStyle = .decimal
nf.minimumFractionDigits = 0
nf.maximumFractionDigits = 1

第二个答案:闭包的结束大括号告诉Swift立即执行闭包。如果您省略了这些括号,则您试图将闭包本身分配给 属性,而不是闭包的 return 值。 App Doc