UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to reuse code with functions

Paul Hudson    @twostraws   

Updated for Xcode 15

When you’ve written some code you really like, and want to use again and again, you should consider putting it into a function. Functions are just chunks of code you’ve split off from the rest of your program, and given a name so you can refer to them easily.

For example, let’s say we had this nice and simple code:

print("Welcome to my app!")
print("By default This prints out a conversion")
print("chart from centimeters to inches, but you")
print("can also set a custom range if you want.")

That’s a welcome message for an app, and you might want it to be printed when the app launches, or perhaps when the user asks for help.

But what if you wanted it to be in both places? Yes, you could just copy those four print() lines and put them in both places, but what if you wanted that text in ten places? Or what if you wanted to change the wording later on – would you really remember to change it everywhere it appeared in your code?

This is where functions come in: we can pull out that code, give it a name, and run it whenever and wherever we need. This means all the print() lines stay in one place, and get reused elsewhere.

Here’s how that looks:

func showWelcome() {
    print("Welcome to my app!")
    print("By default This prints out a conversion")
    print("chart from centimeters to inches, but you")
    print("can also set a custom range if you want.")
}

Let’s break that down…

  1. It starts with the func keyword, which marks the start of a function.
  2. We’re naming the function showWelcome. This can be any name you want, but try to make it memorable – printInstructions(), displayHelp(), etc are all good choices.
  3. The body of the function is contained within the open and close braces, just like the body of loops and the body of conditions.

There’s one extra thing in there, and you might recognize it from our work so far: the () directly after showWelcome. We first met these way back when we looked at strings, when I said that count doesn’t have () after it, but uppercased() does.

Well, now you’re learning why: those () are used with functions. They are used when you create the function, as you can see above, but also when you call the function – when you ask Swift to run its code. In our case, we can call our function like this:

showWelcome()

That’s known as the function’s call site, which is a fancy name meaning “a place where a function is called.”

So what do the parentheses actually do? Well, that’s where we add configuration options for our functions – we get to pass in data that customizes the way the function works, so the function becomes more flexible.

As an example, we already used code like this:

let number = 139

if number.isMultiple(of: 2) {
    print("Even")
} else {
    print("Odd")
}

isMultiple(of:) is a function that belongs to integers. If it didn’t allow any kind of customization, it just wouldn’t make sense – is it a multiple of what? Sure, Apple could have made this be something like isOdd() or isEven() so it never needed to have configuration options, but by being able to write (of: 2) suddenly the function becomes more powerful, because now we can check for multiples of 2, 3, 4, 5, 50, or any other number.

Similarly, when we were rolling virtual dice earlier we used code like this:

let roll = Int.random(in: 1...20)

Again, random() is a function, and the (in: 1...20) part marks configuration options – without that we’d have no control over the range of our random numbers, which would be significantly less useful.

We can make our own functions that are open to configuration, all by putting extra code in between the parentheses when we create our function. This should be given a single integer, such as 8, and calculate the multiplication tables for that from 1 through 12.

Here’s that in code:

func printTimesTables(number: Int) {
    for i in 1...12 {
        print("\(i) x \(number) is \(i * number)")
    }
}

printTimesTables(number: 5)

Notice how I’ve placed number: Int inside the parentheses? That’s called a parameter, and it’s our customization point. We’re saying whoever calls this function must pass in an integer here, and Swift will enforce it. Inside the function, number is available to use like any other constant, so it appears inside the print() call.

As you can see, when printTimesTables() is called, we need to explicitly write number: 5 – we need to write the parameter name as part of the function call. This isn’t common in other languages, but I think it’s really helpful in Swift as a reminder of what each parameter does.

This naming of parameters becomes even more important when you have multiple parameters. For example, if we wanted to customize how high our multiplication tables went we might make the end of our range be set using a second parameter, like this:

func printTimesTables(number: Int, end: Int) {
    for i in 1...end {
        print("\(i) x \(number) is \(i * number)")
    }
}

printTimesTables(number: 5, end: 20)

Now that takes two parameters: an integer called number, and an end point called end. Both of those need to be named specifically when printTablesTable() is run, and I hope you can see now why they are important – imagine if our code was this instead:

printTimesTables(5, 20)

Can you remember which number was which? Maybe. But would you remember six months from now? Probably not.

Now, technically we give slightly different names to sending data and receiving data, and although many people (myself included) ignore this distinction, I’m going to at least make you aware of it so you aren’t caught off guard later.

Take a look at this code:

func printTimesTables(number: Int, end: Int) {

There both number and end are parameters: they are placeholder names that will get filled in with values when the function is called, so that we have a name for those values inside the function.

Now look at this code:

printTimesTables(number: 5, end: 20)

There the 5 and 20 are arguments: they are the actual values that get sent into the function to work with, used to fill number and end.

So, we have both parameters and arguments: one is a placeholder the other is an actual value, so if you ever forget which is which just remember Parameter/Placeholder, Argument/Actual Value.

Does this name distinction matter? Not really: I use “parameter” for both, and I’ve known other people to use “argument” for both, and honestly never once in my career has it caused even the slightest issue. In fact, as you’ll see shortly in Swift the distinction is extra confusing, so it’s just not worth thinking about.

Important: If you prefer to use “argument” for data being passed in and “parameter” for data being received, that’s down to you, but I really do use “parameter” for both, and will be doing so throughout this book and beyond.

Regardless of whether you’re calling them “arguments” or “parameters”, when you ask Swift to call the function you must always pass the parameters in the order they were listed when you created the function.

So, for this code:

func printTimesTables(number: Int, end: Int) {

This is not valid code, because it puts end before number:

printTimesTables(end: 20, number: 5)

Tip: Any data you create inside a function is automatically destroyed when the function is finished.

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.8/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.