Swiftly

Swift 5.1 references for busy coders

forEach

forEach is a functional method that calls a closure on each element in a sequence in the same order as a for-in loop. It does not return anything

Similarities to for-in

forEach loop:

let birds = ["Owl", "Crane"]
birds.forEach {
  print(bird)
}
// Output: 
// Owl
// Crane

for-in equivalent:

let birds = ["Owl", "Crane"]
for bird in birds {
  print(bird)
}
// Output: 
// Owl
// Crane

Differences to for-in

forEach calls a closure on each element. This means that unlike for-in, you cannot use break or continue, and using return will only exit from the current closure call, not the encompassing method. The following example demonstrates this:

func findFirstNegativeNumber(numbers: [Int]) -> Int? {
  for number in numbers {
    if number < 0 { return number }
  }
  
  return nil
}

let numbers = [82, 5, -25, 10, -99]
print(findFirstNegativeNumber(numbers: numbers)) 
// Prints Optional(-25)
func findFirstNegativeNumber(numbers: [Int]) -> Int? {
  numbers.forEach {
    if $0 < 0 { return $0 }
  }
  
  return nil
}

let numbers = [82, 5, -25, 10, -99]
print(findFirstNegativeNumber(numbers: numbers))
// ❌ compilation error: unexpected non-void return value in void function
// if $0 < 0 { return $0 }
//                    ^

What happened here? In the for-in loop, calling return number returns the method findFirstNegativeNumber with our value. But in the forEach loop, calling return $0 actually has the effect of attempting to return the forEach closure, not the method findFirstNegativeNumber, with our value. The closure does not allow a non-void return type, so the code cannot be compiled. (Even if it could, the findFirstNegativeNumber method would then always return nil.)