如 Array 和 Dictionary
forEach(_:)
实例方法中所述:
以相同的方式调用sequence中每个元素的给定闭包 作为 for-in 循环进行排序。
尽管如此,改编自序列概述:
序列是一个值列表,您可以一次逐步浏览其中一个值 时间。 迭代序列元素的最常见方法 是使用 for-in 循环。
暗示通过
forEach(_:)
或 for in
迭代序列:
let closedRange = 1...3
for element in closedRange { print(element) } // 1 2 3
closedRange.forEach { print($0) } // 1 2 3
或(数组):
let array = [1, 2, 3]
for element in array { print(element) } // 1 2 3
array.forEach { print($0) } // 1 2 3
会给出相同的输出。
为什么
forEach(_:)
存在?即使用它代替 for in
循环有什么好处?从性能角度来看它们会相同吗?
作为一个假设,它可能是一种语法糖,尤其是在使用函数式编程时。
forEach
不提供性能优势。事实上,如果你查看源代码,forEach
函数实际上只是执行for
-in
。对于发布版本,与简单地使用 for
-in
相比,此函数的性能开销并不重要,但对于调试版本,它会导致可忽略(但可观察)的性能影响。
forEach
的主要优点是在进行函数式编程时实现的,您可以将其添加到函数调用链中,而无需将先前的结果保存到使用for
时需要的单独变量中-in
语法。所以,而不是:
let objects = array.map { … }
.filter { … }
for object in objects {
…
}
您可以继续使用函数式编程模式:
array.map { … }
.filter { … }
.forEach { … }
结果是功能代码更加简洁,语法噪音更少。
FWIW,Array、Dictionary和Sequence的文档都提醒我们
forEach
引入的限制,即:
您不能使用
或break
语句退出当前 调用continue
闭包或跳过后续调用。body
在
闭包中使用return
语句只会从 当前对body
的调用,不是来自任何外部范围,并且不会跳过 后续通话。body
我最近遇到一个用例,其中使用
forEach
比 for in
更可取。假设您要从图层中删除所有子图层。像下面这样的语句不起作用,因为您需要打开 [CALayer]
for layer in self.videoContainerView.layer.sublayers!
如果子层为零,你将会崩溃。这迫使您首先检查是否存在子层。然而,
forEach
使这变得更加简单,如下所示:
self.videoContainerView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
它们或多或少可以互换,但有两个重要的区别。
break
/continue
仅适用于 for .. in
return
中的forEach
将退出闭包,但不会停止迭代。这样做的原因是
for .. in
是语言中的特殊形式(它允许中断并继续按照你的期望工作)。这是你无法使用语言本身以相同的方式实现的。
但是,
forEach
不是一种特殊形式,可以通过将其编写为函数来相同地重新实现。
extension Sequence {
func myOwnForEach(_ body: (Self.Element) throws -> Void) rethrows {
let it = Self.makeIterator()
while let item = it.next() {
body(item)
}
}
}
除了上述答案之外,区分
for
循环与 forEach
的另一个原因是,使用 for
循环,我们还可以选择使用基于 where
的模式匹配来实现该逻辑,例如
for adBanner in adBanners where !adBanner.isLoading {
上述类型的控制流相关功能使得 for 循环如此强大,但如果我们不需要这种级别的控制,使用对 forEach 的调用可能会给我们带来稍微简单一些的代码。
简而言之,使用
for
循环可以让我们更好地控制迭代