Swift 5.2-有什么新功能?

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'。

Source: https://habr.com/ru/post/undefined/


All Articles