正如Array和Dictionary forEach(_:)
实例方法中所述:
在序列中的每个元素上调用给定的闭包 订购为for-in循环。
然而,改编自Sequence Overview:
序列是一个值列表,您可以在a处逐步执行一个值 时间。 迭代序列元素的最常用方式 是使用 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
循环有什么好处?从性能观点来看,它们是否相同?
作为假设,它可能是一种语法糖,特别是在使用函数式编程时。
答案 0 :(得分:49)
forEach
没有提供任何性能优势。事实上,if you look at the source code,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
的调用,而不是来自任何外部范围,并且不会跳过 后续电话。
答案 1 :(得分:10)
我最近遇到了一个使用forEach
的用例,以for in
为切实可行。我们假设您要从图层中删除所有子图层。如下所示的声明不起作用,因为您需要打开[CALayer]
for layer in self.videoContainerView.layer.sublayers!
如果子图层为零,则会发生崩溃。这会强制您先检查是否有子图层。但是,forEach
使这更加简单,如下所示:
self.videoContainerView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
答案 2 :(得分:7)
它们或多或少是可以互换的,但有两个重要的区别。
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)
}
}
}
答案 3 :(得分:0)
除了上述答案之外,还有一个将 for
循环与 forEach
区分开来的原因是使用 for
循环,我们还可以选择使用基于 where
的模式来实现该逻辑匹配,例如
for adBanner in adBanners where !adBanner.isLoading {
上述与控制流相关的功能使 for 循环如此强大,但如果我们不需要这种级别的控制,则使用对 forEach 的调用可能会使我们的代码看起来稍微简单一些。
简而言之,使用 for
循环可以让我们更好地控制迭代