假设我有一系列我想在每个UITouch上运行的闭包。 这是我使用的代码:
touches.filter { touch in
return touch.phase == .Ended && touch.tapCount == 1
}.forEach { touch in
actionsOnTap.forEach { action in
action(touch)
}
}
这让我觉得有嵌套的forEach语句,我想有一些干净的方法可以完全适用于那种情况,但我想不到它。谁能给我一个提示?
答案 0 :(得分:8)
就个人而言,我喜欢嵌套。我会写:
for touch in touches {
if touch.phase == .Ended {
if touch.tapCount == 1 {
actionsOnTap.forEach {$0(touch)}
}
}
}
对我来说,这很干净(最重要的是)清晰。
答案 1 :(得分:6)
为了提高效率和简洁性,您绝对应该从逻辑中消除filter
并在第一个循环中使用guard
。我同意@Rob's和@matt's建议使用传统的for循环代替forEach
- 至少对于第一个循环。
虽然(可能更干净)替代方案是通过使用for
子句直接将触摸条件逻辑集成到where
循环中,以及可能将forEach
折叠成一个单行(无论哪个更易读)。
我会这样写:
for touch in touches where touch.phase == .Ended && touch.tapCount == 1 {
actionsOnTap.forEach{$0(touch)}
}
答案 2 :(得分:4)
这是forEach
不是for-in
的通用(甚至是适当的常见)替代原因的一个很好的例子。这段代码变得更短(140个字符与186个字符)并且使用传统的for
循环更清晰:
for touch in touches where touch.phase == .Ended && touch.tapCount == 1 {
for action in actionsOnTap {
action(touch)
}
}
它也不像filter
那样创建额外的数组副本。这不是使用filter
的一般原因。 filter
是一个非常强大的工具,应该经常使用,但在这种情况下,使用for
会更加清晰和。
已编辑使用@ originaluser2的where
而不是guard
的建议。这可能是更好的Swift。
答案 3 :(得分:1)
由于您有两种异构数组类型。避免filter
做的额外迭代的另一个解决方案就是过滤你要检查的触摸。
touches.forEach{
guard $0.phase == .Ended && $0.tapCount == 1 else { return }
actions.forEach{ action in
action($0)
}
}