SwiftUI内功之Swift5.2 给我们带来了什么新惊喜
Swift 5.2 现已作为 Xcode 11.4 的一部分公开发布。本文中将带来着大家体验一下Swift 5.2 的新特性。看看给我们带来了什么新的惊喜。
总体而言,Swift 5.2 是一个小版本,它确实带来了许多调整和微小的改进。在此版本中,您将找到:
- 更好的诊断与更有用的错误消息,特别是对于 SwiftUI。
- 可简化某些任务的新功能。
- 主要错误修复。
改进的诊断和错误消息
您总是在第一次尝试时就编写完美的代码吗?如果没有,您会喜欢Swift 5.2中诊断引擎的改进!当您的代码中有错误时,编译器会为您提供有关错误及其位置的更准确的描述。
公平地说,Swift编译器已经很好地报告了代码中的大多数错误。下面的代码:
var str = "10"
let total = str + 5
image.png
错误消息告诉您,您不能使用“ +”运算符来连接字符串和整数。根据您的意图,它还会指出您要采取的解决问题的措施。如果目标是在字符串表示的数字上加5,则可以像这样修复错误:
var str = "10"
let total = Double(str)! + 5
在其他时候,错误消息并没有那么大的帮助。对于与类型检查有关的错误,尤其如此。 Swift 5.2通过专注于类型检查器的改进解决了这个问题。
简化故障排除
看看下面的SwiftUI代码:
struct SquareView : View {
@State var angle = 0.0
var body: some View {
VStack {
TextField("Angle:", text: $angle)
Rectangle()
.rotation(Angle(degrees: angle))
.frame(width: 100.0, height: 100.0)
}
}
}
在Xcode 11.4之前,您将看到的错误消息是
image.png不是很有帮助,是吗?在使用SwiftUI时,经常会看到诸如此类的不清楚的错误消息。这使得使用SwiftUI变得更加困难。找到最简单的错别字就成了繁琐的重新读取,删除或注释掉代码以隔离实际错误的过程。
再看一下代码块。您能发现实际问题吗?提示,与将Double转换为CGFloat无关!
在xcode 11.4您会看到编译器为您提供了更有用,更可行的错误消息:
image.png错误消息会指出错误所在的正确行,并告诉您问题所在:您正在将Double的绑定传递给期望与String绑定的方法。
TextField("Angle", value: $angle, formatter: NumberFormatter.decimalFormatter)
不只是SwiftUI
虽然您通常会在SwiftUI中注意到更好的错误消息传递,但是您还将看到其他Swift代码的改进。
let x: [Int] = [1, 2, 3, 4]
let w: UInt = 4
let filtered = x.filter { ($0 + w) > 42 }
此代码尝试在不进行强制转换的情况下将Int添加到UInt,并且将无法编译。在Swift 5.2之前,编译器显示以下错误:
error: binary operator '+' cannot be applied to operands of type 'Int' and 'UInt'
现在您将看到更精确,更有用的错误消息
error: new-features.playground:34:22: error: cannot convert value of type 'UInt' to expected argument type 'Int'
_ = x.filter { ($0 + y) > 42 }
^
Int( )
新的语法糖
Swift已经在语言中内置了很多语法糖。 Swift 5.2引入了两个新功能,某些开发人员会发现它们非常方便,从而增加了此功能:将类型调用为函数并将键路径表达式用作函数。
注意:语法糖会更改语言的语法,以使其更易于理解或更简洁。
Calling Types as Functions
这项新功能为Swift引入了可静态调用的值。但是,这是什么意思?好吧,这意味着您可以像调用函数一样调用类或其他结构。
要在代码中实现此功能,请向该类型添加一个名为callAsFunction(_ :)的方法。而已!没有第二步。
通过此添加,您现在可以将值作为函数调用。例如,采用代表二次方程的这种类型-一个以ax ^ 2 + bx + c形式表示的常见数学函数:
struct Quadratic {
var a: Double
var b: Double
var c: Double
func callAsFunction(_ x: Double) -> Double {
a * pow(x, 2) + b * x + c
}
}
定义类型使用任何其他值:
let f = Quadratic(a: 4, b: 4, c: 3)
请注意,添加callAsFunction(_:)不会阻止您使用默认 init() 方法。
·
此示例的数学类型选择不是巧合。使用类似于数学表示法的语法是此功能的主要动机。
let y = f(5)
与任何方法一样,可以有多个重写调用callAsFunction(:)以您的类型。如果还希望计算双精度数组的值并将结果作为新数组返回,则可以添加 callAsFunction(:)的第二个:
func callAsFunction(_ xs: [Double]) -> [Double] {
xs.map { callAsFunction($0) }
}
此代码采用双倍数组,并使用 map() 和callAsFunction(_:)的上一个实现(*:)生成具有结果的数组。Swift 确定调用的合适方法,就像对任何其他重写函数调用一样.
let z = f([5, 7, 9])
更简洁的语法
通过在此方法上添加传统方法,可以实现此功能的相同结果。但是,新的语法更简洁,尤其是在值有单个明显操作的情况下。在此示例中,对二次类型的明显操作是计算给定 x 的方程的值。同样,Parser 通常会解析输入作为其主要函数。
机器学习应用
此功能似乎特别侧重于机器学习。在原始建议中,您会看到这一点,因为它特别提到清理神经网络应用程序的语法。它类似于 Python 和交叉兼容。所有这些都使 Swift 更适合 ML 开发人员。
Key Path Expressions as Functions
Swift 5.2现在允许 \Root.value 键路径表达式,只要您已经可以使用 (Root)-> Value函数。
在Code术语中,您可以编写:
orders.map { $0.email }
现在您可以写成
orders.map(\.email)
当前实现将此功能限制为键路径文本表达式。您当前无法编写以下内容,但此功能的讨论建议将来实现
let kp = \.email
users.map(kp)
但是,您可以使用不同的语法完成类似的事情:
let asEmail: (Order) -> String = \Order.email
orders.map(asEmail)
小结
前两个功能为 Swift 带来了更好的功能能力。现在,您可以在以前需要块或闭包的地方使用函数。由于现在可以将key path作为函数传递,因此还可以将key path 传递给实现callAsFunction()。
更多关于key path,请参考《Key Path Expressions as Functions》
Subscripts With Default Arguments
使用 Swift 5.2,现在可以在为类型添加自定义子脚本时声明默认参数。例如,下面是一种使用子脚本进行乘法的简单类型
struct Multiplier {
subscript(x: Int, y: Int = 1) -> Int {
x * y
}
}
let multiplier = Multiplier()
此添加允许您编写指定任意数量的可用子脚本的代码。Swift 对未指定的任何下标使用提供的默认值
multiplier[2, 3]
multiplier[4]
更多subscript请参考https://bugs.swift.org/browse/SR-6118
资料
如果您想了解有关 Swift 进化过程的更多信息,请查看以下链接:
- GitHub change log for Swift. 档简要总结了每个版本的更改
- GitHub listing of Swift Evolution proposals. 本文档为每个建议提供指向 GitHub 页面的链接。用它来阅读给定更改背后的原因和思考过程的完整描述
- Swift.org bugs and issues dashboard. 使用此站点查看 Swift 中报告的 Bug 和问题的完整描述、讨论和活动。
技术交流
QQ:3365059189
SwiftUI技术交流QQ群:518696470
推荐文章
CoreData篇
- SwiftUI CoreData做个数据收集App实现增删改查(含源码)
- SwiftUI数据存储之做个笔记App 新增与查询(CoreData)
- SwiftUI进阶之存储用户状态实现登录与登出
- SwiftUI 数据之List显示Sqlite数据库内容(2020年教程)
TextField篇
- 《SwiftUI 一篇文章全面掌握TextField文本框 (教程和全部源码)》
- 《SwiftUI实战之TextField风格自定义与formatters》
- 《SwiftUI实战之TextField如何给键盘增加个返回按钮(隐藏键盘)》
- 《SwiftUI 当键盘出现时避免TextField被遮挡自动向上移动》
- 《SwiftUI实战之TextField如何给键盘增加个返回按钮(隐藏键盘)》