Swift 5.2的第一个beta版本刚刚出现在Xcode 11.4 beta中,并且语言发生了变化,代码的大小和使用的内存减少了,新的诊断系统将使您能够快速检测到错误。将KeyPath表达式用作函数
我们定义以下结构:struct User {
let name: String
let age: Int
let bestFriend: String?
var canVote: Bool {
age >= 18
}
}
让我们创建一些结构实例,并将其放入数组中:let eric = User(name: "Eric Effiong", age: 18, bestFriend: "Otis Milburn")
let maeve = User(name: "Maeve Wiley", age: 19, bestFriend: nil)
let otis = User(name: "Otis Milburn", age: 17, bestFriend: "Eric Effiong")
let users = [eric, maeve, otis]
现在注意:如果需要获取所有用户的名称数组,则可以按以下步骤进行操作:let userNames = users.map(\.name)
print(userNames)
以前,我们需要使用闭包:let oldUserNames = users.map { $0.name }
以相同的新方式,您可以让所有可以投票的用户:let voters = users.filter(\.canVote)
在这里,我们得到了拥有最好朋友的每个人:let bestFriends = users.compactMap(\.bestFriend)
用户定义类型的值
创建一个具有lowerBound和upperBound属性的Dice结构,然后添加callAsFunction函数。因此,每次获得骰子值时,我们将获得一个随机值:struct Dice {
var lowerBound: Int
var upperBound: Int
func callAsFunction() -> Int {
(lowerBound...upperBound).randomElement()!
}
}
let d6 = Dice(lowerBound: 1, upperBound: 6)
let roll1 = d6()
print(roll1)
在这里,我们得到一个从1到6的随机数,这与直接调用callAsFunction()完全相同。我们可以做同样的事情:let d12 = Dice(lowerBound: 1, upperBound: 12)
let roll2 = d12.callAsFunction()
print(roll2)
Swift会根据如何定义callAsFunction()自动选择正确的调用。例如,您可以添加多个参数,更改返回值,甚至在必要时将方法标记为变异。在这里,我们将创建一个StepCounter结构,该结构捕获已采取的步骤数并发出已完成的步骤数是否达到10,000的信号:struct StepCounter {
var steps = 0
mutating func callAsFunction(count: Int) -> Bool {
steps += count
print(steps)
return steps > 10_000
}
}
var steps = StepCounter()
let targetReached = steps(count: 10)
callAsFunction()还支持引发和重新引发,并且可以定义多个callAsFunction()方法,与常规重载一样。下标可以声明默认参数
将下标添加到类型时,可以使用默认参数。例如,如果我们有一个带有自定义下标的PoliceForce结构以列出单位中的人员,则可以在数组超出其边界的情况下添加默认参数以将其返回:struct PoliceForce {
var officers: [String]
subscript(index: Int, default default: String = "Unknown") -> String {
if index >= 0 && index < officers.count {
return officers[index]
} else {
return `default`
}
}
}
let force = PoliceForce(officers: ["Amy", "Jake", "Rosa", "Terry"])
print(force[0])
print(force[5])
在这里,我们在输出中得到“ Amy”,然后得到“ Unknown”,因为我们没有索引为5的数组元素。由于我们编写了默认default,因此可以设置一个自定义值,例如:print(force[-1, default: "The Vulture"])
新的和改进的诊断
Swift 5.2引入了一种新的诊断体系结构,旨在提高Xcode开发错误消息的质量和准确性。当使用SwiftUI代码时,这尤其明显,因为Swift经常会生成错误的肯定错误消息。例如,考虑以下代码:struct ContentView: View {
@State private var name = 0
var body: some View {
VStack {
Text("What is your name?")
TextField("Name", text: $name)
.frame(maxWidth: 300)
}
}
}
在这里,我们尝试将视图TextField与整数关联 州属性错误。在这种情况下,Swift 5.1将为frame()修饰符'Int'无法转换为'CGFloat?'生成错误。但是Swift 5.2和更高版本正确地识别了$ name绑定中的错误:无法将类型'Binding'的值转换为预期的参数类型'Binding'。