改进的隐式成员语法
在 Swift 5.4 之前,如果您希望红色略微透明,则需要编写以下代码:
struct ContentView: View {
var body: some View {
Text("You're not my supervisor!")
.foregroundColor(Color.red.opacity(0.5))
}
}
从 Swift 5.4 起,编译器可以支持多个链式的成员,这意味着可以推断 Color 类型:
struct ContentView: View {
var body: some View {
Text("You're not my supervisor!")
.foregroundColor(.red.opacity(0.5))
}
}
函数中的多个可变参数
Swift 5.4 之前,只能有一个可变参数。
Swift 5.4 ,可有多个可变参数。
例子:
编写一个函数来接受一个可变参数,该参数存储足球比赛期间进球的时间,以及第二个可变参数,用于对得分球员的姓名进行评分
func summarizeGoals(times: Int..., players: String...) {
let joinedNames = ListFormatter.localizedString(byJoining: players)
let joinedTimes = ListFormatter.localizedString(byJoining: times.map(String.init))
print("\(times.count) goals where scored by \(joinedNames) at the follow minutes: \(joinedTimes)")
}
调用该函数
summarizeGoals(times: 18, 33, 55, 90, players: "Dani", "Jamie", "Roy")
Result 构建器
// This is invalid Swift, and will not compile.
func makeSentence2() -> String {
"Why settle for a Duke"
"when you can have"
"a Prince?"
}
上面的代码将无法工作,因为 Swift 不理解我们的意思。但是,我们可以创建一个 Result 构建器,该构建器了解如何使用所需的任何转换将多个字符串转换为一个字符串,如下所示:
@resultBuilder //@resultBuilder属性告诉 SwiftUI 以下类型应视为结果生成器。
struct SimpleStringBuilder {
//每个结果生成器必须提供至少一个称为 buildBlock() 的静态方法,该方法应获取某种数据并将其转换。
//示例接收零个或多个字符串,将它们连接起来,然后将它们作为单个字符串发送回去。
static func buildBlock(_ parts: String...) -> String {
parts.joined(separator: "\n")
}
}
最终结果是我们的 SimpleStringBuilder
结构成为结果生成器,这意味着我们可以在需要其字符串连接能力的任何地方使用 @SimpleStringBuilder
。
我们可以像下面这样直接使用 SimpleStringBuilder.buildBlock():
let joined = SimpleStringBuilder.buildBlock(
"Why settle for a Duke",
"when you can have",
"a Prince?"
)
print(joined)
但是,因为我们在 SimpleStringBuilder 结构中使用了 @resultBuilder 批注,所以我们也可以将其应用于函数,如下所示:
@SimpleStringBuilder func makeSentence3() -> String {
"Why settle for a Duke"
"when you can have"
"a Prince?"
}
print(makeSentence3())
如果您想查看实际的结果生成器示例,请查看 GitHub 上的 Awesome Function Builders 存储库(https://github.com/carson-katri/awesome-function-builders)。
现在支持局部变量的属性包装器
属性包装器最初是在 Swift 5.1 中引入的,它是一种通过简单,可重复使用的方式将附加功能附加到属性的方法,但是在 Swift 5.4 中,它们的行为得到扩展以支持将其用作函数中的局部变量。
例如,我们可以创建一个属性包装器,以确保其值永远不会低于零:
@propertyWrapper struct NonNegative<T: Numeric & Comparable> {
var value: T
var wrappedValue: T {
get { value }
set {
if newValue < 0 {
value = 0
} else {
value = newValue
}
}
}
init(wrappedValue: T) {
if wrappedValue < 0 {
self.value = 0
} else {
self.value = wrappedValue
}
}
}
从 Swift 5.4 起,我们可以在常规函数中使用该属性包装器,而不仅仅是将其附加到属性上。例如,我们可能编写了一款游戏,玩家可以得或失,但得分不得低于0:
func playGame() {
@NonNegative var score = 0
// player was correct
score += 4
// player was correct again
score += 8
// player got one wrong
score -= 15
// player got another one wrong
score -= 16
print(score)
}
网友评论