iOS 项目上线经验ios开源项目ios

SwiftUI内功之Swift5.2 给我们带来了什么新惊喜

2020-04-24  本文已影响0人  iCloudEnd

Swift 5.2 现已作为 Xcode 11.4 的一部分公开发布。本文中将带来着大家体验一下Swift 5.2 的新特性。看看给我们带来了什么新的惊喜。

总体而言,Swift 5.2 是一个小版本,它确实带来了许多调整和微小的改进。在此版本中,您将找到:

改进的诊断和错误消息

您总是在第一次尝试时就编写完美的代码吗?如果没有,您会喜欢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 开发人员。

更多细节可参考,Callable values of user-defined nominal types

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 进化过程的更多信息,请查看以下链接:

技术交流

QQ:3365059189
SwiftUI技术交流QQ群:518696470

推荐文章

CoreData篇

TextField篇

JSON文件篇

上一篇下一篇

猜你喜欢

热点阅读