Updated for Xcode 14.2
There’s one last closure-related topic I want to look at, which is how to write functions that accept other functions as parameters. This is particularly important for closures because of trailing closure syntax, but it’s a useful skill to have regardless.
Previously we looked at this code:
func greetUser() {
print("Hi there!")
}
greetUser()
var greetCopy: () -> Void = greetUser
greetCopy()
I’ve added the type annotation in there intentionally, because that’s exactly what we use when specifying functions as parameters: we tell Swift what parameters the function accepts, as well its return type.
Once again, brace yourself: the syntax for this is a little hard on the eyes at first! Here’s a function that generates an array of integers by repeating a function a certain number of times:
func makeArray(size: Int, using generator: () -> Int) -> [Int] {
var numbers = [Int]()
for _ in 0..<size {
let newNumber = generator()
numbers.append(newNumber)
}
return numbers
}
Let’s break that down…
makeArray()
. It takes two parameters, one of which is the number of integers we want, and also returns an array of integers.makeArray()
we create a new empty array of integers, then loop as many times as requested.generator
function that was passed in as a parameter. This will return one new integer, so we put that into the numbers
array.The body of the makeArray()
is mostly straightforward: repeatedly call a function to generate an integer, adding each value to an array, then send it all back.
The complex part is the very first line:
func makeArray(size: Int, using generator: () -> Int) -> [Int] {
There we have two sets of parentheses and two sets of return types, so it can be a bit of a jumble at first. If you split it up you should be able to read it linearly:
makeArray()
.size
.generator
, which itself accepts no parameters and returns an integer.makeArray()
– returns an array of integers.The result is that we can now make arbitrary-sized integer arrays, passing in a function that should be used to generate each number:
let rolls = makeArray(size: 50) {
Int.random(in: 1...20)
}
print(rolls)
And remember, this same functionality works with dedicated functions too, so we could write something like this:
func generateNumber() -> Int {
Int.random(in: 1...20)
}
let newRolls = makeArray(size: 50, using: generateNumber)
print(newRolls)
That will call generateNumber()
50 times to fill the array.
While you’re learning Swift and SwiftUI, there will only be a handful of times when you need to know how to accept functions as parameters, but at least now you have an inkling of how it works and why it matters.
There’s one last thing before we move on: you can make your function accept multiple function parameters if you want, in which case you can specify multiple trailing closures. The syntax here is very common in SwiftUI, so it’s important to at least show you a taste of it here.
To demonstrate this here’s a function that accepts three function parameters, each of which accept no parameters and return nothing:
func doImportantWork(first: () -> Void, second: () -> Void, third: () -> Void) {
print("About to start first work")
first()
print("About to start second work")
second()
print("About to start third work")
third()
print("Done!")
}
I’ve added extra print()
calls in there to simulate specific work being done in between first
, second
, and third
being called.
When it comes to calling that, the first trailing closure is identical to what we’ve used already, but the second and third are formatted differently: you end the brace from the previous closure, then write the external parameter name and a colon, then start another brace.
Here’s how that looks:
doImportantWork {
print("This is the first work")
} second: {
print("This is the second work")
} third: {
print("This is the third work")
}
Having three trailing closures is not as uncommon as you might expect. For example, making a section of content in SwiftUI is done with three trailing closures: one for the content itself, one for a head to be put above, and one for a footer to be put below.
SPONSORED From March 20th to 26th, you can join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer!
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.