Swift 5.8 内置于 Xcode 14.3,增加了如下的几个重要的新特性。
功能返回部署
- 增加了
@backDeployed(before: ...)
属性,允许将修饰的功能扩展到没有将其作为应用程序二进制接口(ABI)的旧操作系统中,即在旧版本上使用新 API。
@backDeployed(before: iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4)
-
@backDeployed
要求当前所在类型与修饰内容的访问权限不低于public
。 -
@backDeployed
适用于计算属性与方法。
public struct Person {
@available(iOS 11, *)
@backDeployed(before: iOS 16.4)
public var age: Int {
return Int.random(in: 0 ... 100)
}
@available(iOS 13.0, *)
@backDeployed(before: iOS 16.4)
public func info() {}
}
[weak self]改变
Swift 5.3 之后 self 可以在闭包中有条件省略,Swift 5.8 之后类中的[weak self]
也可以省略 self。
import UIKit
class ViewController: UIViewController {
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
let action = UIAction(title: "计数") { [weak self] _ in
guard let self = self else { return }
// Swift 5.8之前
// self.count = 1
// print(self.count)
// Swift 5.8之后
count = 1
print(count)
}
let navItem = UIBarButtonItem(systemItem: .done, primaryAction: action)
navigationItem.leftBarButtonItem = navItem
}
}
取消result builders中对变量的使用限制
Swift 5.4 中引入的 result builders 对局部变量有一些限制:不能使用lazy
、不能被计算、不能有观察器、不能附加属性包装等。Swift 5.8 之后解除了所有使用限制。
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
lazy var name = "zhangsan"
var age: Int {
return 10
}
var sex: String = "male" {
willSet {
print(newValue)
}
didSet {
print(oldValue)
}
}
Text("Hello, (name), (age), (sex)")
Button("change") {
sex = "female"
}
}
.padding()
}
}
支持集合类型向下类型转换
Swift 5.8 之前集合类型不支持直接向下类型转换,需要使用if let as?
。Swift 5.8 之后语法上支持直接向下类型转换,但也仅仅是语法不再报错,并不能保证转换成功。
class Vehicle {
var name: String
init(name: String) {
self.name = name
}
}
class Bicycle: Vehicle {
func run() {
print("Bicycle (name) Run run")
}
}
func test(vehicles: [Vehicle]) {
// Swift 5.8之前
if let bicycles = vehicles as? [Bicycle] {
for bicycle in bicycles {
bicycle.run()
}
} else {
print("error")
}
// Swift 5.8之后
switch vehicles {
case let bicycles as [Bicycle]:
for bicycle in bicycles {
bicycle.run()
}
default:
print("default")
}
}
#file与#filepath
#file
的输出不再包含文件的完整路径,只包含模块与文件名,如果需要显示完整路径使用新的编译符号#filepath
。
func test() {
print(#file)
print(#filepath)
}
test()