Advertisement
  1. Code
  2. Swift
Code

Swift from Scratch: An Introduction to Functions

by
Difficulty:BeginnerLength:MediumLanguages:
This post is part of a series called Swift from Scratch.
Swift from Scratch: Optionals and Control Flow
Swift from Scratch: Function Parameters, Types, and Nesting

To get anything done in Swift, you'll need to learn the ins and outs of functions. Functions are exceptionally powerful and flexible in Swift. The basics are simple—especially if you've worked with other programming languages before—but because of Swift's flexible syntax it can easily become complex if you're not familiar with the basics.

In this article, we'll focus on those basics first and explore the more complex syntax and use cases in the next article. It's important that you don't skim the basics as they are essential to understand where a function's power comes from in Swift. Let's start with an example to dissect the anatomy of a function in Swift.

1. Learn by Example

A function is nothing more than a block of code that can be executed whenever it's needed. I'd like to start with an example to discuss the basic anatomy of a Swift function. Fire up Xcode and create a new playground. Add the following function definition to the playground.

A function begins with the func keyword and is followed by the name of the function, printHelloWorld in our example. As in many other languages, the name of the function is followed by a pair of parentheses that contain the function's parameters, the function's input.

The body of the function is wrapped in a pair of curly braces. The printHelloWorld function contains one statement in which we print the string Hello World! in the standard output. This is what a basic function looks like in Swift. The syntax is simple, clean, and minimalist.

You can invoke the function by typing the name of the function, followed by a pair of parentheses.

2. Parameters

Let's make the above example a bit more complex by adding parameters to the function definition. This simply means that we provide the function with input values it can use in the function's body. In the following example, we define the printMessage function, which accepts one parameter, message, of type String.

A function can accept multiple parameters or input values. The parameters are wrapped by the parentheses that follow the function's name. The name of the parameter is followed by a colon and the parameter's type. As you remember, this is very similar to declaring a variable or constant. It simply says that the message parameter is of type String.

Instead of printing a hard-coded string like we did in the printHelloWorld function, we print the message parameter's value. This makes the function flexible and more useful.

Invoking the function is very similar to what we saw earlier. The only difference is that we pass in an argument when invoking the function.

Note that the terms parameters and arguments are often used interchangeably, but there is a subtle, semantic difference in Swift. In Swift, parameters are the values specified in the function definition while arguments are the values passed to the function when it is invoked.

Multiple Parameters

As I mentioned earlier, the syntax of functions is very flexible and it shouldn't surprise you that it's perfectly possible to pass multiple arguments to a function. In the next example, we create a variation on the printMessage function that allows us to print the message multiple times.

While the name of the function is identical to that of the original printMessage function, the function's type is different. It's important you understand the previous sentence. Read it again.

Each function has a type, consisting of the parameter types and the return type. We'll explore return types in a moment. Functions can have the same name as long as their type is different as shown by the previous two function definitions.

The type of the first function is (String) -> () while the type of the second function is(String, Int) -> (). The name of both functions is the same. Don't worry about the -> symbol. Its meaning will become clear in a few moments when we discuss return types.

The second printMessage function defines two parameters, message of type String and times of type Int. This definition illustrates one of the features Swift has adopted from Objective-C, readable function/method names. While the name of the function is printMessage, by reading the names of the function's parameters, it's easy to understand what the function is supposed to do.

In the second printMessage function, we create a for-in loop to print the message string times times. We use the half-open range operator, ..<, as we saw earlier in this series.

When we start typing printMessage in the playground, Xcode displays both functions in the autocompletion menu. Thanks to the function's type, it's easy to choose the function we're interested in. Calling the second printMessage function is as simple as:

Default Values

One of my favorite features is the ability to define default values for parameters. This may sound silly if you're coming from a language that has had this feature for ages, but this is pretty great if you've been working with C and Objective-C for many years.

In short, Swift allows developers to define default values for the parameters of a function. Let's define a new function that prints the current date in a specific format. Make sure you add the following import statement at the top of your playground to import the UIKit framework.

Let's first define the printDate function without making use of default values for any of the parameters.

If you're not familiar with the Foundation framework and you're not understanding what's happening in the function body, then that's fine. The focus of this example isn't on the implementation of formatting the date. In printDate, we use the value of the format parameter to format the value of date. If we don't pass in a value for the format parameter, Swift will let us know by throwing an error.

We can remedy this by defining a default value for the function's second parameter as shown in the updated function definition below.

Defining a default value is as simple as specifying a value in the list of parameters in the function's definition. The result is that Swift will no longer complain and the error disappears.

What if we do want to pass in a value for the format parameter? Let's try it out and see what Swift tells us.

Because the format parameter has a default value and is therefore optional, we need to pass in the argument's name to tell Swift what parameter we're referring to. The fix is very simple as you can see below.

Note that Apple recommends to position parameters with a default value at the end of the list of parameters. This is certainly a good idea and common in most other programming languages that support optional parameters.

3. Return Type

The functions we've seen so far don't return anything to us when we invoke them. Let's make the printDate function more useful by returning the formatted date as a string, instead of printing the formatted date from within the function. This requires two changes as you can see below.

The first thing we change is the function's definition. After the list of parameters we specify the return type, String. The return type is preceded by the -> symbol. If you've worked with CoffeeScript, then this will look familiar.

Instead of printing the formatted date using the println function, we use the return keyword to return the value from the function. That's all we need to do. Let's try it out.

We invoke the printDate function, store the returned value in the constant formattedDate, and print the value of formattedDate in the standard output. Note that the name of the printDate function no longer reflects what it does so you may want to change it to formatDate.

No Return Type

The other functions we've defined in this tutorial didn't have a return type. When a function doesn't have a return type, it isn't necessary to include the -> symbol in the function definition.

A few paragraphs earlier, I told you that none of the functions we had defined returned a value to us. That's actually not entirely true. Let me explain the nitty-gritty details with an experiment. Add the following line to your playground and see what happens.

This is interesting. Swift doesn't have a problem that we store the return value of the printHelloWorld function in a constant, but it does complain that it is unable to infer the type of the value constant.

What's happening here? Every function in Swift returns a value, even if we don't define a return type in the function definition. When a function doesn't explicitly specify a return type, the function implicitly returns Void, which is equivalent to an empty tuple, or () for short. You can see this in the playground's output pane as shown in the above screenshot.

We can get rid of the above warning by explicitly declaring the type of value, an empty tuple. I agree that it's not very useful to store an empty tuple in a constant, but it illustrates you that every function has a return value.

Tuples

Another great feature of Swift is the ability to return multiple values from a function by returning a tuple. The following example illustrates how this works. Let me repeat that it's not important that you understand how the timeComponentsForDate function does its job. The focus is the return value of the timeComponentsForDate function, a tuple with three elements.

The function accepts one argument, an NSDate instance, and returns a tuple with three labeled values. Labeling the tuple's values is only for convenience, it is possible to omit the labels.

However, as the following example illustrates, labeling the values of the tuple returned from the function is very convenient and makes your code easier to understand.

It's also possible to return an optional value from a function if there are scenarios in which the function has no value to return. This is as simple as defining the return type of the function as optional as shown below.

Conclusion

In this tutorial, we've focused on the basics of functions in Swift. It's important that you understand the syntax of functions, because in the next article we will explore more advanced functions that build upon what we've covered in this tutorial.

I encourage you to read the article again if necessary and, more importantly, write a few functions in a playground to become familiar with the syntax. The basics are easy to understand, but you only get the hang of them by practicing.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.