Python实战社群
Java实战社群
长按识别下方二维码,按需求添加
扫码关注添加客服
进Python社群▲
扫码关注添加客服
进Java社群▲
作者 | Tibor Bödecs
来源 | https://theswiftdev.com/
Swift 5.3将是一个令人兴奋的新版本。这篇文章展示了最新的 Swift 特性。
从 Apple 在 3 月下旬公布 Swift 5.3 发布流程至今,5.3 分支上已经实现了许多新功能。如果你想了解一下都有什么新功能,可以使用 swiftenv 安装最新快照来体验一下。
Package Manager 更新
Swift Package tool 5.3 版本引入了一些非常好的功能。
资源
随着 SE-0271 的实现,Swift Package Manager 最终可以将资源文件与代码打包在一起。我相信这是一个非常受欢迎的新功能,因为有些库需要嵌入资产文件,但目前为止 SPM 还无法支持。
本地化资源
SE-0278 扩展了资源支持,通过此实现,可以为 Swift 软件包声明本地化的资源。SE-0278 的描述解释了提议的详细信息,如果需要随包一起发布本地化文件,可以看看。
二进制依赖
另一个很棒的事情是 SPM 最终将能够使用二进制依赖项。SE-0272添加了此功能,因此如果希望提供闭源的人现在可以使用此功能。这样可以在给定的路径或位置设置 binaryTarget 依赖性,并且可以将二进制文件用于库或或执行文件。
条件目标依赖
SE-0273 提供了一个很好的补充,可以使用基于给定平台的依赖项。这意味着在为特定平台构建产品时,可以将产品用于一个 target。
以上功能是对 SPM 的重要补充,希望 Xcode 也能从这些功能中受益,并且我们还将在即将发布的 IDE 版本中看到一些重大的新的增强功能。
语言特性
5.3 版本中引入了许多有趣的新提议。
多个尾随闭包
SE-0279 是争议最大的新提案之一。当我第一次看到它时,我不确定是否需要它,为什么有人会花这么大的力气消除一些括号呢?????
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// old
UIView.animate(withDuration: 0.3, animations: {
self.view.alpha = 0
}, completion: { _ in
self.view.removeFromSuperview()
})
// still old
UIView.animate(withDuration: 0.3, animations: {
self.view.alpha = 0
}) { _ in
self.view.removeFromSuperview()
}
// new
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0
}
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0
} completion: { _ in
self.view.removeFromSuperview()
}
}
}
如你所见,这主要是一种语法糖,但是我说服自己拥有它是很好的。
为枚举类型合成 Comparable
由于 SE-0266,Enum 类型不必显式实现 Comparable 协议。
enum Membership: Comparable {
case premium(Int)
case preferred
case general
}
([.preferred, .premium(1), .general, .premium(0)] as [Membership]).sorted()
Comparable 协议是自动合成的,就像其它类型的 Equatable 和 Hashable 一样。当然,如果需要,您可以提供自己的实现。
枚举的 case 实现协议
Swift 的枚举是功能强大构建基块,现在它们变得更好了。????
protocol DecodingError {
static var fileCorrupted: Self { get }
static func keyNotFound(_ key: String) -> Self
}
enum JSONDecodingError: DecodingError {
case fileCorrupted
case keyNotFound(_ key: String)
}
SE-0280 的主要目标是解除现有限制,如果枚举提供的 case 其命名和参数能符合协议的要求,则枚举可以作为协议的一个实现。
基于类型的程序入口点
SE-0281为我们提供了一个新的 @main 属性,可以使用该属性来定义应用程序的入口点。这是一个很好的补充,不必再编写 MyApp.main()
方法,而只需用main属性标记 MyApp 对象。
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
static func main() {
print("App will launch & exit right away.")
}
}
不推荐使用UIApplicationMain和NSApplicationMain属性,而推荐使用@main,我敢打赌这将在下一个主要版本中发布...
多模式 Catch
SE-0276 是另一种语法糖,非常方便同时捕获多个异常。
do {
try performTask()
}
catch TaskError.someRecoverableError {
recover()
}
catch TaskError.someFailure(let msg), TaskError.anotherFailure(let msg) {
showMessage(msg)
}
这消除了在 catch 块中使用 switch case。✅
Float16
SE-0277 将 Float16 添加到标准库中。
let f16: Float16 = 3.14
泛型数学函数也即将推出...
Self 的改变
SE-0269 aka。对于那些不太愿意写 self 的人来说,在不太可能发生引用循环时提高@escaping 闭包中隐式 self 的可用性是一个不错的选择。????
//old
execute {
let foo = self.doFirstThing()
performWork(with: self.bar)
self.doSecondThing(with: foo)
self.cleanup()
}
//new
execute { [self] in
let foo = doFirstThing()
performWork(with: bar)
doSecondThing(with: foo)
cleanup()
}
这将允许我们仅将self写入捕获列表,而稍后在块内将其忽略。
完善 didSet 语义
SE-0268 是一个底层改进,使 didSet 行为更佳,更可靠。????
class Foo {
var bar = 0 {
didSet { print("didSet called") }
}
var baz = 0 {
didSet { print(oldValue) }
}
}
let foo = Foo()
// This will not call the getter to fetch the oldValue
foo.bar = 1
// This will call the getter to fetch the oldValue
foo.baz = 2
简而言之,以前总是调用属性的getter,但是从现在开始,仅当我们使用 didSet 块中的 oldValue 参数时,才调用该方法。
在非连续元素上添加集合操作
SE-0270 添加了一个 RangeSet 类型来表示多个不连续的范围,以及用于创建和使用范围集的各种集合操作。
var numbers = Array(1...15)
// Find the indices of all the even numbers
let indicesOfEvens = numbers.subranges(where: { $0.isMultiple(of: 2) })
// Perform an operation with just the even numbers
let sumOfEvens = numbers[indicesOfEvens].reduce(0, +)
// sumOfEvens == 56
// You can gather the even numbers at the beginning
let rangeOfEvens = numbers.moveSubranges(indicesOfEvens, to: numbers.startIndex)
// numbers == [2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15]
// numbers[rangeOfEvens] == [2, 4, 6, 8, 10, 12, 14]
该建议还通过一些使用RangeSet类型的API方法扩展了Collection类型,如果您经常使用范围,则应该看看。????
上下文范型声明的 where子句
如果仅引用泛型参数,则使用 SE-0267 可以实现函数并在其上施加where约束。考虑以下代码段:
protocol P {
func foo()
}
extension P {
func foo() where Self: Equatable {
print("lol")
}
}
这在老版本上无法编译,但是在 Swift 5.3 之后它将像魔术一样工作。
添加可访问未初始化存储的字符串初始化器
SE-0263 添加了一个新的String初始化器,使您可以使用未初始化的缓冲区。
let myCocoaString = NSString("The quick brown fox jumps over the lazy dog") as CFString
var myString = String(unsafeUninitializedCapacity: CFStringGetMaximumSizeForEncoding(myCocoaString, ...)) { buffer in
var initializedCount = 0
CFStringGetBytes(
myCocoaString,
buffer,
...,
&initializedCount
)
return initializedCount
}
// myString == "The quick brown fox jumps over the lazy dog"
通过使用这种新的init方法,您不必再担心不安全的指针了。
Swift的未来发展
目前,在Swift的开发面板上还有6个被接受的提案,其中一个正在接受审核。Swift 5.3将包含一些社区期待已久的惊人新功能。我很高兴该语言朝着正确的方向发展。????
程序员专栏 扫码关注填加客服 长按识别下方二维码进群
近期精彩内容推荐:
在看点这里好文分享给更多人↓↓