Swift : How $0 works in Array.forEach?

19,941

Solution 1

Short answer

Look at this code

let nums = [1,2,3,4]
nums.forEach { print($0) }

Here the closure following forEach

I mean this part { print($0) }

is executed 4 times (once for every element inside the array). Each time it is executed $0 contains a copy of the n-th element of your thenums array.

So the first time contains 1, then 2 and so on...

Here's the output

1
2
3
4

Comparing forEach with the for-in construct

So can we say tha $0 is like the n value in the following code?

for n in nums {
    print(n)
}

Yes, it has pretty much the same meaning.

How does it work?

The forEach method accept a closure. The closure has this signature.

(Self.Generator.Element) throws -> Void

When you use the forEach it makes a "contract" with you.

  1. You provide to the forEach a closure that accept a single param in input where the param has the same type of the Array
  2. The forEach will apply that closure to each element of the array.

Example

nums.forEach { (n) in
    print(n)
}

However in Swift you can omit explicit names for the parameters of a closure. In this inside the closure you can refer that params using $0 for the first param, $1 for the second one and so on.

So the previous snippet of code can be also be written like below

nums.forEach {
    print($0)
}

Solution 2

Shorthand Argument Names

Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.

If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted, because the closure expression is made up entirely of its body:

reversed = names.sort( { $0 > $1 } ) Here, $0 and $1 refer to the closure’s first and second String arguments.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html

Solution 3

Functions like "forEach", "sort" take closure as an argument. These closures also have arguments, for example to a closure of "forEach" function you can provide your own name of an argument, or use the default one "$0". If the closure has multiple arguments (like function "sort" does) the default ones are gonna be "$0", "$1" if you provide none. Keep in mind closures can expect you to return some value, like "sort" does. You got the logic, here is example:

let array: [String] = []
array.forEach { element in
    element.doStuff()
}

array.forEach {
    $0.doStuff()
}

let sortedArray = array.sort { first, second in
    return first < second
}

let sortedArray = array.sort {
    return $0 < $1
}
Share:
19,941
SaRaVaNaN DM
Author by

SaRaVaNaN DM

Passionate about mobile technologies and would love to explore new things always. Mobile App Developer with 10 years of experience. Platform : iOS, React Native, Android Programming Languages : Swift, Objective-C, Java, C, Javascript, CSS, Html IDE : Xcode, VS Code, Android Studio, Intellij Voip : PJSip Version Control : Git, SVN

Updated on July 22, 2022

Comments

  • SaRaVaNaN DM
    SaRaVaNaN DM almost 2 years

    I have seen most of the swift developer are starting using .forEach, understood its another way to iterate array. But what is the meaning of '$0' and how it works? If it's an index then it should increment 0,1,2...

    @IBOutlet var headingLabels: [UILabel]!
    ....
    
    headingLabels.forEach { $0.attributedText = NSAttributedString(string: $0.text!, attributes: [NSKernAttributeName: 1]) }
    
  • SaRaVaNaN DM
    SaRaVaNaN DM almost 8 years
    In my case, it's alway $0. But still i can able to iterate all the elements.
  • Asdrubal
    Asdrubal almost 8 years
    $0 is the first argument in each iteration. Think of a for loop like this: for (index, element) in list.enumerate() { print("Item \(index): \(element)") } $0 would represent element. The only reason you would use this is to write code faster with less lines
  • java_doctor_101
    java_doctor_101 over 7 years
    @appzYourFile, how does the contract work under the hood? Do you know where I can find the source of this? Basically I am trying to figure out that when you call a method called foreach on an instance of type array how does that function know about the value present inside the array since all we are passing in that function is an empty closure variable. Right? How doe for each function actually gets the data of the array to iterate over? Thanks!
  • Luca Angeletti
    Luca Angeletti over 7 years
    @nitinsh99: Take a look here. Specifically the Inferring Type From Context and Shorthand Argument Names paragraphs
  • Motti Shneor
    Motti Shneor over 7 years
    in $0, the 0 (zero) denotes the index of the function/closure argument - not the index of item in the array. This notion is familiar to unix shell-script and C developers where there are arg0 arg1 etc. denoting the arguments of a script or function.
  • Edison
    Edison about 7 years
    @appzYourLife Great explanation. I've seen this on an online iOS interview test.