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
我的问题是:
- 为什么不能
NumberFormatters
在闭包外创建
案例?
- 括号
()
末尾代表什么
关闭?我的猜测是它是自调用的,但为什么需要这样呢?
到目前为止,我从未见过以这种方式编写的闭包。 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
在阅读 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
我的问题是:
- 为什么不能
NumberFormatters
在闭包外创建 案例? - 括号
()
末尾代表什么 关闭?我的猜测是它是自调用的,但为什么需要这样呢?
到目前为止,我从未见过以这种方式编写的闭包。 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