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,我敢打赌这将在下一个主要版本中发布... 多模式 CatchSE-0276 是另一种语法糖,非常方便同时捕获多个异常。 do { try performTask() } catch TaskError.someRecoverableError { recover() } catch TaskError.someFailure(let msg), TaskError.anotherFailure(let msg) { showMessage(msg) }
这消除了在 catch 块中使用 switch case。✅ Float16SE-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将包含一些社区期待已久的惊人新功能。我很高兴该语言朝着正确的方向发展。👍
|