
随着Xcode 10.2的发布,Swift 5.0可用了,但是下一版本的工作仍在继续,并且已经有了关于它的期望的消息。
Swift 5.1的一个关键功能是
模块稳定性 ,它使我们能够使用第三方库,而不必担心使用它们创建的Swift编译器版本。 看起来就像我们在Swift 5.0中获得的
ABI稳定性 ,但是有一点点不同:ABI稳定性解决了运行时Swift版本中的差异,以及编译时的模块稳定性。
除了这项重要的创新之外,我们还将在Swift中进行一些重要的改进,在本文中,我们将通过示例对它们进行介绍,以便您可以看到它们的实际应用。
普世自我
SE-0068扩展了
Self的使用,因此它引用包含在类,结构和枚举中的类型。 当需要在运行时确定某事物的确切类型时,这通常对于动态类型很有用。
作为示例,请考虑以下代码:
class NetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(NetworkManager.maximumActiveRequests).") } }
在这里,我们在
NetworkManager类中定义静态属性
maximumActiveRequests ,并添加
printDebugData()方法以打印此属性。 在这里一切都很好,但是直到我们决定从
NetworkManager继承之前:
class ThrottledNetworkManager: NetworkManager { override class var maximumActiveRequests: Int { return 1 } }
在此继承人中,我们更改了maximumActiveRequests属性,使其现在等于1,但是如果调用
printDebugData() ,它将从父类中
推断出该值:
let manager = ThrottledNetworkManager() manager.printDebugData()
在这里,我们应该得到1而不是4,然后是救援SE-0068:我们可以使用
Self (大写的“ S”)来引用当前类型。 因此,现在我们可以像这样重写父类的
printDebugData()方法:
class ImprovedNetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(Self.maximumActiveRequests).") } }
也就是说,
Self的工作方式与早期版本的Swift中的协议相同。
没有歧义的警告
Swift中的
Optionals被实现为带有两个选项的枚举:
some和
none 。 如果我们创建具有
none选项的枚举并将其包装在
optional中 ,则可能导致混淆。 例如:
enum BorderStyle { case none case solid(thickness: Int) }
当使用非可选时,一切都是干净的:
let border1: BorderStyle = .none print(border1)
这将输出“无”。 但是,如果我们对这个枚举使用可选的,那么我们将遇到一个问题:
let border2: BorderStyle? = .none print(border2)
Nil将在此处打印,因为Swift认为.none表示optional为
空 ,尽管实际上它是
具有 BorderStyle.none
值的可选。
在Swift 5.1中,如果出现此类歧义,将显示警告:
“假设您的意思是'Optional.none'; 您是说'BorderStyle.none'吗?”
因此,开发人员将被告知,使用他的代码,并非一切都可以顺利进行。
匹配可选和非可选枚举
当结合使用可选/非可选文本和整数值时,Swift足够聪明,可以理解switch / case构造,但对于枚举而言却不是。
现在在Swift 5.1中,我们可以使用switch / case来匹配枚举可选和非可选选项:
enum BuildStatus { case starting case inProgress case complete } let status: BuildStatus? = .inProgress switch status { case .inProgress: print("Build is starting…") case .complete: print("Build is complete!") default: print("Some other build status") }
Swift可以将可选枚举映射到非可选选项,并且此处将显示“ Build is starting ...”。
比较订购的收藏
SE-0240引入了计算有序集合之间差异的功能,并将结果比较结果应用于集合。 对于那些在表视图中具有复杂集合并且需要使用动画添加或删除许多元素的开发人员来说,这可能很有趣。
基本原理很简单-Swift 5.1提供了一个新的方法
差异(from :) ,它确定两个有序集合之间的差异-添加和删除哪些元素。 这适用于包含符合
Equatable协议的项目的任何有序集合。
为了证明这一点,我们将创建两个值的数组,计算一个值与另一个值的差,然后遍历差列表并应用它们以使两个集合相同。
注意:由于Swift现在是作为Apple操作系统的一部分分发的,因此应将新语言工具与
#available检查一起使用,以确保代码在支持所需功能的OS上运行。 对于在将来可能发布的未知且未宣布的操作系统上运行的功能,使用特殊的版本号“ 9999”,这表示:“我们尚不知道正确的版本号”。
var scores1 = [100, 91, 95, 98, 100] let scores2 = [100, 98, 95, 91, 100] if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) for change in diff { switch change { case .remove(let offset, _, _): scores1.remove(at: offset) case .insert(let offset, let element, _): scores1.insert(element, at: offset) } } print(scores1) }
对于更高级的动画,我们可以在结果差异列表中使用第三个参数:
associatedWith 。 因此,我们可以编写.insert(让偏移量,let元素,
让 relatedWith
) ,而不是
.insert(让偏移量,let元素,_ )。 这使我们能够同时跟踪更改对:将集合中的元素向下移动两个位置即删除元素,然后将其添加,并且
associatedWith将这两个更改“绑定”在一起,并允许您考虑此移动。
您可以使用新的apply
()方法一口气地应用它们,而不必一一手动应用差异。
if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) let result = scores1.applying(diff) ?? [] }
创建未初始化的数组
SE-0245为数组引入了新的初始化器,该初始化器未使用默认值填充它。 它较早以私有API的形式提供,这意味着Xcode不会在代码完成时提示它,但是如果需要它,并且您知道将来可能不再使用此功能,则可以使用它。
要使用初始化程序,请设置数组的大小,然后传递用值填充数组的闭包。 闭包将收到指向可变缓冲区的不安全指针,以及第二个参数,您可以在其中指示实际使用了多少个值。
例如,我们可以创建一个包含10个随机整数的数组,如下所示:
let randomNumbers = Array<Int>(_unsafeUninitializedCapacity: 10) { buffer, initializedCount in for x in 0..<10 { buffer[x] = Int.random(in: 0...10) } initializedCount = 10 }
有几个规则:
- 您不需要使用所请求的整个卷,但是不能超过它。 也就是说,如果将数组的大小设置为10,则可以将initializedCount设置在0到10的范围内,但不能设置为11。
- 例如,如果您没有初始化数组中使用的元素,则将initializedCount设置为5,但没有为元素0到4提供真实值,则它们很可能会收到随机值。 如您所知,这是一个不好的选择。
- 如果您未设置initializedCount ,则它将等于0,并且分配的所有数据都将丢失。
是的,我们可以使用
map()重写代码:
let randomNumbers2 = (0...9).map { _ in Int.random(in: 0...10) }
这显然更具可读性,但效果却不那么有效:我们先创建一个范围,然后创建一个新的空数组,为其指定大小,然后“遍历”整个范围,对每个元素应用闭包。
结论
Swift 5.1仍在开发中,尽管Swift本身的最终分支已经通过,但其他一些相关项目的更改仍然可见。
因此,最重要的更改是
模块稳定性 ,并且众所周知,开发团队正在为此而努力。 他们没有给出确切的发布日期,尽管他们说Swift 5.1的开发时间比Swift 5.0的开发时间短得多,而Swift 5.0需要特别集中精力和精力。 我们可以假定访问WWDC19,但是很明显,当您需要赶到某个特定日期时,情况并非如此。
另一点值得关注。 对该列表的两项更改(“警告,如果无选项时有歧义”和“匹配可选枚举和非可选枚举”)不是Swift演变的结果,而是被视为错误并进行了调整。