1. Performance, functional programming and collections in Swift

函数式编程通常是用Swift完成的,而且非常容易,很容易就会影响性能。迭代大型集合并执行过滤或映射等操作是常见的,应该明智地使用。

当这些方法组合在一起时,性能经常会下降,就像过滤器后面跟着第一个。最佳实践列表。

1.1. Prefer contains over first(where:) != nil

验证一个对象是否存在于一个集合中可以通过多种方式来完成。确保使用contains以获得最佳性能。

Best practice

let numbers = [0, 1, 2, 3]
numbers.contains(1)

Bad practice

let numbers = [0, 1, 2, 3]
numbers.filter { number in number == 1 }.isEmpty == false
numbers.first(where: { number in number == 1 }) != nil

1.2. Prefer checking isEmpty over comparing count to zero.

描述这一原因的最佳方法是引用isEmpty文档。

当您需要检查集合是否为空时,使用isEmpty属性而不是检查count属性是否等于零。对于不符合RandomAccessCollection的集合,访问count属性将遍历集合的元素。

Best practice

let numbers = []
numbers.isEmpty

Bad practice

let numbers = []
numbers.count == 0

1.3. Checking for an empty String with isEmpty

Swift中的字符串可以看作是字符的集合。这意味着上述性能实践也适用于字符串,应该使用isEmpty检查空字符串。

Best practice

myString.isEmpty

Bad practice

myString == ""
myString.count == 0

1.4. Get the first object matching a condition

迭代一个集合以获得匹配给定条件的第一个对象,可以使用filter后跟first来完成,但最佳实践是使用first(where:)代替。

一旦第一次满足条件,后者就停止在集合上迭代。filter将继续遍历整个集合,即使它可能已经命中了匹配条件的对象。

显然,对于last(where:)也是一样的。

Best practice

let numbers = [3, 7, 4, -2, 9, -6, 10, 1]
let firstNegative = numbers.first(where: { $0 < 0 })

Bad practice

let numbers = [3, 7, 4, -2, 9, -6, 10, 1]
let firstNegative = numbers.filter { $0 < 0 }.first

1.5. Getting the minimum or maximum element in a collection

在对集合进行排序并选择第一个对象之后,可以找到集合中的最小元素。对于最大元素也是如此。但是,这需要先对整个数组进行排序。在这种情况下,使用min()和max()方法是最佳实践。

Best practice

let numbers = [0, 4, 2, 8]
let minNumber = numbers.min()
let maxNumber = numbers.max()

Bad practice

let numbers = [0, 4, 2, 8]
let minNumber = numbers.sorted().first
let maxNumber = numbers.sorted().last

1.6. Making sure all objects match a condition

很容易使用filter和isEmpty来验证集合中的所有对象都匹配给定的条件。随着SE-0207在Swift 4.2中引入,我们现在可以使用allSatisfy(_:)来验证集合的每个元素都匹配给定的条件。

Best practice

let numbers = [0, 2, 4, 6]
let allEven = numbers.allSatisfy { $0 % 2 == 0 }

Bad practice

let numbers = [0, 2, 4, 6]
let allEven = numbers.filter { $0 % 2 != 0 }.isEmpty

1.7. Using SwiftLint to ensure best practices

这些示例中的大多数都是在SwiftLint中实现的,可以帮助您确保使用了这些最佳实践。