Swift 4.2的第二个更新版本于2018年推出,Swift 4.2对该语言进行了一些重大改进。 阅读这篇文章,以了解它们如何帮助您编写更好的代码。
包含在此版本的改进列表中:
- SE-0194 :添加
CaseIterable
协议以自动生成所有可能的枚举案例的数组。 - SE-0195 :动态成员查找语法糖。
- SE-0196 :新的编译器指令
#warning
和#error
。 - SE-0197 :新的
removeAll(where:)
方法可为集合执行优化的就地过滤器。 - SE-0199 :新的
toggle()
方法可轻松切换/翻转布尔值。 - SE-0202 :新的本机随机数生成器。
- SE-0206 :新的
Hasher
类型,用于改进和简化对Hashable
协议的一致性。 - SE-0207 :新的
allSatisfy()
方法可验证序列中的所有元素是否通过条件。 - SE-0143 :改善条件一致性。
枚举大小写迭代
首先,Swift 4.2引入了用于枚举的新协议。 如果使枚举符合CaseIterable
协议,则可以以类似数组的方式遍历枚举列表,列出所有可能的情况。 例如,采用以下枚举:
enum ShirtSizeOptions: CaseIterable {
case small, medium, large, extra-large
}
您可以使用新的allCases
属性像迭代一样遍历此枚举列表,如下所示:
for size in ShirtSizeOptions.allCases{
print("Shirt size is \(size)")
}
动态成员查找
添加了新属性@dynamicMemberLookup
,以允许Swift编译器在访问属性时利用下标方法,以便您可以为任意名称提供点语法,然后在运行时解析它们。 这从Python的约定中脱颖而出。 定义下标时,您将传递dynamicMember
以及将返回的属性列表,如下所示:
@dynamicMemberLookup
class Shirt {
subscript(dynamicMember member: String) -> String {
let values = ["size": "small", "color": "Light Blue", "type": "kids"]
return values[member, default: ""]
}
}
此示例说明了如何在字符串中查找动态成员并返回一个字符串,同时在字典中查找该成员的名称。 以下实现说明了它是如何工作的:
let shirt = Shirt()
print(shirt.size) //small
print(shirt.color) //Light Blue
print(shirt.gender) //
实例化该类时,前两个属性是动态可发现的,并且将在运行时以类型安全的String
返回成员的默认值。 最后一个属性( gender
)在类中不存在,并且不会返回任何内容,因为在查找返回值时,我们使用空字符串作为默认值。 您不限于返回字符串-实际上,您可以从动态成员查找(包括闭包)中返回任何内容。
新的编译器警告和错误指令
这项新功能对于拥有Objective-C背景的许多人来说是过去的爆炸,因为该联盟为Swift引入(或重新引入了)编译器指令以标记代码中的问题。 这两个指令是#warning
和#error
。
#warning
指令可帮助开发人员标记有问题的代码块,因此这些问题将在Xcode中显示为警告。 该#error
指令,但是,将强制编译时错误,如果,例如,你想迫使开发人员看你的代码和完成的代码块,例如,是非常有用的,加入自己的API令牌或凭证代替占位符。 以下示例说明了后者的用例:
class APIServiceManager {
#error("Please enter your own personal cloud token below")
var cloudToken: String = ""
}
对集合执行就地过滤的新方法
通过新的removeAll(where:)
方法,开发人员现在可以通过传递闭合条件来对集合执行就地过滤。 假设您有一系列衬衫,并且想要删除特定的值medium
。 您之前可能已经做过类似的事情:
let shirtSizes = [“small”, “medium”, “large”, “extra-large”]
let mediumShirtRemoved = shirtSizes.filter { !$0.contains(“medium”) }
print(mediumShirtRemoved) // [“small“, “large“. “extra-large“]
通过添加removeAll(where:)
,您可以运行更多内存优化操作来显式地就地删除:
var shirtSizes = ["small", "medium", "large", "extra-large"]
shirtSizes.removeAll { $0.contains("medium") }
print(shirtSizes) //["small", "large", "extra-large"]
轻松在布尔值之间切换或翻转
SE-0199是一个简单但值得欢迎的改进,它通过toggle()
方法引入了布尔切换。 以一种熟悉的模式,您将具有如下所示的内容:
var isShirtLarge = true
print(isShirtLarge) //true
isShirtLarge = !isShirtLarge
print(isShirtLarge) //false
通过添加此新方法,您可以编写:
var isShirtLarge = true
print(isShirtLarge) //true
isShirtLarge.toggle()
print(isShirtLarge) //false
新的本机随机数生成器
令人惊讶的是,在Swift 4.1之前,该语言缺少本机随机数生成器,从而迫使开发人员改为依赖arc4random_uniform()
返回均匀分布的随机数。 现在,您只需调用random()
方法以及特定范围即可使用:
var shirtSizes = [“small”, “medium”, “large”, “extra-large”]
let randomShirt = Int.random(in: 0 ..< shirtSizes.count-1)
print(shirtSizes[randomShirt]) //medium
除Int
以外的其他数字类型(包括Float
, Double
, CGFloat
, Bool
和Array
都支持此方法。
Bool
使您可以返回随机的true
或false
响应。 该建议还要求使用两个与数组相关的方法: shuffled()
方法(用于随机化数组顺序)和randomElement()
(用于从数组中返回随机元素)。
以下是如何使用新的shuffled()
方法的示例:
var shirtSizes = [“small”, “medium”, “large”, “extra-large”]
let newShirtSizesOrder = shirtSizes.shuffled()
print(newShirtSizesOrder) //[“large”, “medium”, “extra-large”, “small”]
我们还可以使用randomElement()
方法来改进我们之前获得随机衬衫大小的代码:
var shirtSizes = ["small", "medium", "large", "extra-large"]
//let randomShirt = Int.random(in: 0 ..< shirtSizes.count-1)
//print(shirtSizes[randomShirt])
print(shirtSizes.randomElement()) //extra-large
哈希协议一致性的改进
Swift通过新的Hasher
结构改进了自定义对象类型符合Hashable
协议的方式-使其变得更快,更简单,更安全。 以前,无论何时创建字典或集合,都将具有符合Hashable
的类型,从而为您免费提供优化的哈希。 但是,当实现自己的符合Hashable
的类型时,您需要创建自己的算法来手动计算hashValue
。
Swift 4.1通过推断可用于唯一标识对象的内容,显着改善了此问题:
class Shirt: Hashable {
var size: String
var color: ColorEnum
}
但是,当您必须使用更复杂的对象类型时,仍然需要实现一种算法以返回唯一的hashValue
。
Swift 4.2引入了新的Hasher
结构,可以为您计算唯一的哈希值:
struct Shirt: Hashable {
static func == (lhs: Shirt, rhs: Shirt) -> Bool {
return lhs.size == rhs.size
}
var size: Int?
var id: Int?
func hash(into hasher: inout Hasher) {
hasher.combine(size)
hasher.combine(id)
}
}
要实现新的Hasher
结构,请创建一个Hasher
实例并提供要组合的自定义类型。 Hasher实例将创建并返回唯一的哈希。
确保序列中的所有元素都满足条件
Swift 4.2接受的最后一个功能是SE-0207 ,它添加了一个新方法allSatisfy()
,以验证序列中的所有项目是否符合特定的序列条件。 尽管您已经可以使用contains
方法来验证集合中的某个元素是否满足条件,但是allSatisfy
方法根据整个元素集是否满足条件来返回一个布尔值。
allSatisfy
的以下实现声明是否超过$ 20的条件满足shirtOrderPrices
的整个顺序:
var shirtOrderPrices = [42.99, 42.99, 23.90, 42.99, 32.99]
let weHaveMedium = shirtOrderPrices.allSatisfy { $0 > 20 } //true
结论
Swift仍然是一门不断增长的语言,不断增加新功能并进行辩论。 您可以通过访问Swift Evolution跟踪最新的提案列表以及每个提案的接受状态。
翻译自: https://code.tutsplus.com/tutorials/whats-new-in-swift-42--cms-32129