Swift – ¿Evita anidar para cada cierre?

Digamos que tengo una variedad de cierres que quiero ejecutar en cada UITouch. Aquí está el código que uso:

touches.filter { touch in return touch.phase == .Ended && touch.tapCount == 1 }.forEach { touch in actionsOnTap.forEach { action in action(touch) } } 

Me molesta que haya nested la statement de Each, y creo que hay una forma limpia que se puede aplicar exactamente para ese caso, pero no puedo pensar en ello. ¿Alguien puede darme una pista?

Definitivamente debería eliminar el filter de su lógica y, posiblemente, usar un guard dentro del primer ciclo, en aras de la eficiencia y la concisión. También estoy de acuerdo con la sugerencia de @ Rob y @ matt de usar un bucle tradicional en lugar de forEach , al less para el primer bucle.

Aunque una alternativa (quizás incluso más limpia) es integrar la lógica condicional táctil en el bucle for directamente mediante el uso de la cláusula where , y posiblemente doblar su forEach en una sola línea (lo que encuentre más legible).

Lo escribiría así:

 for touch in touches where touch.phase == .Ended && touch.tapCount == 1 { actionsOnTap.forEach{$0(touch)} } 

Personalmente, me gusta la anidación. Yo escribiría:

 for touch in touches { if touch.phase == .Ended { if touch.tapCount == 1 { actionsOnTap.forEach {$0(touch)} } } } 

Para mí, eso está limpio y (sobre todo) claro.

Este es un buen ejemplo de por qué forEach no es un reemploop universal (o incluso común) para for-in . Este código se hace más corto (140 caracteres vs 186 caracteres) y más claro simplemente usando un bucle tradicional for :

 for touch in touches where touch.phase == .Ended && touch.tapCount == 1 { for action in actionsOnTap { action(touch) } } 

Tampoco crea una copy extra de la forma en que lo hace el filter . Esta no es una razón general para no usar el filter . filter es una herramienta muy poderosa que debe usarse con frecuencia, pero en este caso, es más clara y más eficiente de usar.

Editado para usar la sugerencia de @ originaluser2 de where y no de guard . Eso probablemente sea mejor Swift.

Como tiene dos types de arreglos heterogéneos. otra solución que evita la iteración extra que hace el filter es filtrar los toques que desea comprobar.

 touches.forEach{ guard $0.phase == .Ended && $0.tapCount == 1 else { return } actions.forEach{ action in action($0) } }