WWDC20 第四弹 - Swift的新特性
2020/7/22 23:04:27
本文主要是介绍WWDC20 第四弹 - Swift的新特性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
此次Swift5.3引入了许多新特性,不仅在语言本身,还增强了Xcode对Swift的支持及对Swift Packages的更新。本文并不打算对所有更新进行说明(实际上也完全没有必要),仅会探索一些重要且有意思的feature,如果想要深入全面了解,WWDC20也有非常多的Session来介绍这些内容,蜗牛都已经整理并贴在了文末。
代码缩进
Xcode12对代码缩进做了不少改善,主要有以下几个方面:
- 链式方法调用,特别是那些涉及嵌套或尾随闭包的调用
- 当元素对齐时,不再缩进调用参数、参数列表、数组和字典文字或元组中的多行表达式
- 多行条件语句(if,guard 和 while)
以guard
为例,在此之前缩进相当僵硬,后面条件总是无法和第一个对齐,并且包体内缩进也有问题
@escaping
闭包中隐式self
在此之前,声明了@escaping
的闭包需要显式使用self
,但现在如果开发者能够确定不存在循环引用,Swift允许在@escaping
闭包中隐式使用self
。
如果用户已经在闭包的捕获列表中明确捕获了self
,则现在允许在@escaping
闭包中隐式使用self
class Test { var x = 0 func execute(_ work: @escaping () -> ()) { work() } func method() { execute { [self] in x += 1 } } } 复制代码
另外,如果self
是值类型,无需明确捕获,隐式self
在@escaping
闭包中也可使用:
struct Test { var x = 0 func execute(_ work: @escaping () -> Void) { work() } mutating func method() { execute { x += 1 } } } 复制代码
上述代码在之前就会报错:Reference to property 'x' in closure requires explicit 'self.' to make capture semantics explicit
。
减少增量编译
如果有这样的一个类,包含了多个类、结构体或协议,
struct A { } struct B { } ... 复制代码
在此之前,例如修改A,使用A或B的任何文件都将重新编译,而现在仅会对使用A的文件重新编译,这将对修改后编译速度有不错的提升。
如果编译遇到问题,可以在 Other Swift Flags 添加 -disable-type-fingerprints 以将其禁用。如果仍有问题,可以添加 -disable-fine-grained-dependencies ,以禁用新的依赖项基础结构。
Binary Size
Apple一直都在优化二进制文件的大小,从 Swift 4 以来,一直到 5.3 版本,从一开始的 2.3 倍,如今已经优化到 1.5 倍。
对于Swift为什么会需要这么多的binary size,官方解释是因为Swift带有一些“安全”相关的Feature,这些在生成的产物中需要有一定量的代码实现。
以官方Demo对比,使用Xcode12的编译结果就比用Xcode11下降了43%。
Swift Platform Support
更新了支持的多个平台,包括:
- Apple 各OS
- Ubuntu 16.04, 18.04, 20.04
- CentOS 8
- Amazon Linux 2
- Windows(Coming soon,Swift 5.3)
对于非App开发的同学有用,蜗牛只是搬运工🙃。
Dirty Memory优化
脏内存由于不能被系统回收,能够有效减少当然是不错的,官方测试后对比了堆内存的使用情况:
Emm.....感觉并不是很明显。
代码补全
Apple做了一些小优化,支持更多场景的代码补全,比较实用的一个例子就是支持补全三元表达式:
上面还是小打小闹,Apple宣称Xcode12将在补全速度上有大幅提升。在某些场景下,其性能会强于Xcode11.5高达15倍。
以Apple的节操,15倍的优化我是不信的,之前WWDC19说App启动速度较上个版本大幅优化,但实际上个版本较上上个版本已经大幅增加了启动速度,最终优化效果并没有那么夸张。
多尾随闭包
Swift5.3以前只支持最后一个闭包参数可以使用尾随闭包:
UIView.animate(withDuration: 5, animations: { // ... }) { (_) in // ... } 复制代码
现在Swift支持多个尾随闭包,看起来更优雅了(I like it😍):
UIView.animate(withDuration: 5) { // ... } completion: { (_) in // ... } 复制代码
try catch支持多模式
Swift5.3以前,try...catch...
在多Error
类型判断时,对代码会造成一定的冗余,例如:
Swift5.3扩展了try...catch...
语法,使其catch
支持捕获不同的Error
,类似switch...case...
:
比较Enum
在Swift5.3中,让一个enum
遵循Comparable
协议就可支持比较,非常实用的扩展。
枚举的cases支持protocol witnesses(这个要咋翻呢🧐)
在Swift5.3以前,enum
必须实现protocol
中的方法,而不能直接使用cases
来代替。
protocol Foo { static var bar: Self { get } static func baz(arg: Int) -> Self } enum SomeEnum: Foo { static var bar: SomeEnum { return ._bar } static func baz(arg: Int) -> SomeEnum { return ._baz(arg: arg) } case _bar case _baz(arg: Int) } 复制代码
上述方式在使用起来很繁琐,Swift5.3对此作了优化,cases
可以直接认为是protocol
的实现,而无需写重复代码。
protocol Foo { static var bar: Self { get } static func baz(arg: Int) -> Self } enum SomeEnum: Foo { case bar case baz(arg: Int) } 复制代码
新增Float16
此前的Float32
和Float64
分别是Float
和Double
的别名,并不是新的浮点格式,
而Float16
是一个新 IEEE 754 标准浮点格式。
优点:
- 更好的性能:由于仅占两个字节的内存,因此可以在 SIMD 寄存器或内存页中容纳两倍的数量,而在支持的硬件上,这通常会使性能提高一倍。
- 与 C/Objective-C 里 __fp16 类型的互操性
缺点:
- 显而易见,就是低精度和小范围
@main
声明入口函数
在 ArgumentParser 发布了之后,大家也想要类似于 @UIApplicationMain
这样的注解去声明入口函数,并且Windows平台支持多种入口函数类型,此时 main.swift
就无法很好地满足使用。
Swift5.3支持使用@main
关键字来注解声明入口函数:
感兴趣的可以翻阅@main: Type-Based Program Entry Points。
Numerics库
Numerics
是一个 Apple 开源的 Swift 库,通过范型约束,提供更简单的方式,来使用所有标准库里的浮点型进行数值计算,涵盖几乎所有基本的数学函数。
作为一个Swift only的库,Numerics
是一个很好地学习如何编写和封装更优雅 Swift 代码的范例。
Package Manager
Swift Package Manager
发布到现在已经四年了,今年迎来两个非常重要的功能:
- 二进制依赖分发
- 资源文件
Emm...... Cocoapods不香吗🤭,后续有研究再补充。
New Logger
Logger
用于收集和处理日志信息,以理解和调试应用中的意外行为。在开发中,往往会遇到难以复现的bug,或者无法在debug下直接调试。通过Logger
帮助开发者理解及处理这类疑难杂症。
使用起来也很方便:
import os func test() { // subsystem 用于区分是哪个应用的日志,可以使用bundleID // category 用于区分是应用的哪个模块 let logger = Logger(subsystem: "com.example.TestWWDC20", category: "testos") logger.log("Started a task \(taskId)") } 复制代码
再单例封装下,添加一下业务模块支持,既好用也方便统一管理。
- 性能优化
由于日志一般量级很大,读写会影响性能,线上版本都是杜绝非必需的日志打印,例如通过print
函数。为了解决这个问题,Swift和Xcode做了高度优化,只有当 log 信息真正显示的时候,才会将其转换为字符串。
- 隐私保护
为了保护隐私,当在 log 消息中加入非数字类型的数据时,默认会标记为private
,这是为了确保应用在实机运行时,不会泄漏个人信息。
当然,log 信息也支持由开发者显式标记隐私等级:
那如何对比非公开的日志呢?Logger
提供一种 equality-preserving hash
方法。在经过处理之后,不会显示真正的数据,但也能让我们判断这两条信息是否一样。
如果应用从 Xcode 中启动,即使这条 log 信息是非公开的,在 console 中也会完全显示出来,以便开发者调试。
- 日志等级
Swift 提供了五种不同的等级:Debug,Info,Notice(默认),Error,Fault。
对于不同等级的日志,其持久化的能力也是不一样的:
相应的,各自性能也有差别:
可以看出 Debug 日志记录的性能是很快的,所以调用比较耗时的函数相对安全:
- 格式化
Logger
支持对写入的参数进行格式化,方便阅读和对比数据:
使用了格式化后,数据就很清晰了,复制到 Numbers 也方便很多:
相关Session
- What's new in Swift
- Swift packages: Resources and localization
- Distribute binary frameworks as Swift packages
- Explore logging in Swift
- Explore numerical computing in Swift
原创不易,文章有任何错误,欢迎批(feng)评(kuang)指(diao)教(wo),顺手点个赞👍,不甚感激!
这篇关于WWDC20 第四弹 - Swift的新特性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值