3月底,针对Xcode 11.4发布了Swift 5.2。它改进了错误诊断,依赖性分析并扩展了SwiftPM功能。在Habré上已经发布了一些更改的概述,在同一篇文章中,考虑了语言本身的演变以及可能的用法示例。
快捷方式将keyPath放入函数中,其中输入参数是对象本身,而结果是其属性。让我们看一个例子。创建一系列简单模型:struct Model {
let isHidden: Bool
}
let modelArray = [Model(isHidden: true), Model(isHidden: false)]
通过isHidden属性过滤数组。以下是3个示例,它们具有相同的结果:
let funcIsHidden: (Model) -> Bool = \.isHidden
modelArray.filter(funcIsHidden)
modelArray.filter(\.isHidden as (Model) -> Bool)
modelArray.filter(\.isHidden)
在以下示例中,声明的功能不起作用:
let selfFunc: (Model) -> Model = \.self
modelArray.compactMap(selfFunc)
modelArray.compactMap(\.self as (Model) -> Model)
modelArray.compactMap(\.self)
此外,与keyPath不同,autocomplet不起作用。使用诸如过滤,映射,归约,排序等功能的数组很方便。所有功能参数都可以设置为默认值。创建一个Box结构,其中包含一个元素数组和一个下标函数来访问它们。struct Box {
let items: [String]
subscript(_ index: Int = 0) -> String {
items[index]
}
}
现在,要访问第一个元素,您可以省略索引:let box = Box(items: ["laptop, , mobile phone"])
let firstItem = box[]
SR-2189本地功能从外部可见性支持默认参数
在日常实践中,很少使用局部功能。可能难以证明其用途。不过,我承认在某些情况下这可能派上用场。例如,我们将创建一个函数,在其中描述本地函数:func getXPosition() {
func calculateWidth(x: CGFloat = minX) -> CGFloat { ... }
let minX: CGFloat = 0
...
}
作为calculateWidth函数的默认参数,我们可以使用getXPosition函数中的值。功能类似于@dynamicCallable,允许您将值用作函数。但这是“静态调用”的实现。实际上,一切都非常简单:要调用函数,您可以将值称为方法。创建一个播放器结构:struct Player {
private(set) var isRunning = false
mutating func callAsFunction() {
isRunning.toggle()
}
}
创建一个Player实例,并将其作为函数引用:var player = Player()
print(player.isRunning)
player()
print(player.isRunning)
同时,禁止强制转换,因此,将对象作为函数传递:
let playerAsFunc = player as () -> Void
您可以向类,结构或协议中添加与callAsFunction一样多的方法:extension Player {
func callAsFunction(isRunning: Bool = false) throws { ... }
func callAsFunction() -> Bool { ... }
}
可以在作为数学函数,复杂表达式的值或该值具有一个主导函数的情况下应用。但是,您不应滥用此功能,因为它可能会引起误解。SR-4206修复了带有通用参数覆盖功能的错误
现在,覆盖该功能,您将无法更改或添加对泛型类型的限制。例如,创建一个CarBuilder类并通过覆盖add方法从其继承:protocol PowerfullEngine { }
class CarBuilder {
func add<T>(engine: T) {}
}
class MercedesBuilder: CarBuilder {
override func add<T>(engine: T) {}
override func add<T: PowerfullEngine>(engine: T) {}
}
在“自我”限制的情况下,扩展程序将应用该限制。例如,创建具有类限制的Menu和extension协议:protocol Menu {}
class SideMenu: Menu {
var sectionHeight = 0
}
extension Menu where Self: SideMenu {
var menuHeight: Int {
get { sectionHeight * 20 }
set { sectionHeight = newValue / 20 }
}
}
同时,设置程序是非突变的,就像协议具有类限制一样。现在,删除了用于键入标签的转换功能时。因此,您可以使用标签强制转换功能。以前,此功能仅在没有标签的功能中起作用:func setX(x: Int) {}
(setX as (Int) -> Void)(5)
但是,将不会保存默认值:func setPoint(x: Int, y: Int = 0) {}
(setPoint as (Int, Int) -> Void)(5, 1)
这也适用于泛型,因此此代码不再有效。typealias Point<T> = T
func set(x: Int) {}
(set as Point)(5)
(set as Point)(x: 5)
SR-11841在惰性集合中按预期顺序调用了filter(_ :)函数
创建一个惰性集合并调用count方法:let lazyArray = [0]
.lazy
.filter { _ in print("A"); return true }
.filter { _ in print("B"); return true }
_ = lazyArray.count
之前,通话结果相反:BA。SR-2790现在,许多UnsafePointer / UnsafeBufferPointer系列的类型初始化器发出警告
该限制适用于在函数调用之外不存在的字符串,数组和inout参数。创建一个在初始化期间将UnsafePointer作为参数的结构:struct Game {
let info: UnsafePointer<Int8>
}
func createGame() {
var i: Int8 = 0
_ = Game(info: .init(&i))
_ = Game(info: [1, 2])
_ = Game(info: "")
}
此版本中有9处更改,但是它们确实带来了新功能。我认为当前使用最多的是KeyPath函数。我们期待下一个版本。显然,它将在Windows上支持Swift,并且会出现一些有趣的功能,例如在转义闭包中使用self而不通过self访问*(SE-0269)和泛型(SE-0267)的功能将会扩展。资源