A Beginner’s Guide to Swift Functions

Learn how to reduce code repetition in your Swift projects by using functions. You’ll also learn the many benefits of using Swift functions in this article.
Written by

Iñaki Narciso

Updated on

Apr 29 2024

Table of contents

    When coding, we typically write code that tells the app to perform a series of steps to achieve a particular goal. When we want to perform this series of steps again somewhere in our code, we can’t help but introduce some form of repetition. Repetition of code by itself isn’t really harmful to the app, but it does for readability, especially when you’re working with other people who read your code regularly.

    A way to lessen code repetition is to group your code into functions. A function is basically a block of code that performs a specific task. You give a function a name (that describes the work it does), and this name can be used to “call” the function to perform all the work you’ve coded it to.

    Defining a Function

    /// A function that accepts two Int numbers
    /// adds them, then returns the sum
    func add(x: Int, y: Int) -> Int {
      return x + y
    }

    The func keyword

    Functions are defined by using the func keyword, followed by the name that describes the work it does. From the code snippet above, the function’s name is add, because its task is to add two numbers and return the sum.

    Function Parameters

    A function can accept a number of parameters enclosed by parentheses. From the code snippet above, the add function accepts two Int parameters named x and y. These two Int parameters are then added inside the body of the function to calculate the sum and return the value.

    When declaring parameters, you need to specify the name and the type of each parameter. The name of a function parameter is also called an argument label. From the code snippet above, the parameters x and y are the argument labels, while Int is the type of both parameters. You can use Swift primitive types such as Int or String, or it can be instances of custom types you’ve written such as a class, struct, enum, or protocol. You can also pass functions as parameters but it’s best left to explore after you learn more about closures.

    When you want to declare a function that accepts no parameter, you can simply do so by not specifying any parameter argument labels inside the parentheses.

    /// A function that accepts no parameter
    func greetHello() {
      print("Hello!"
    }
    
    /// A function that accepts a single parameter
    func sayHello(name: String) {
      print("Hello \(name)!")
    }
    
    /// A function that accepts more than one parameters
    func sayHello(personA: String, personB: String) {
      print("Hello \(personA) and \(personB)!"
    }

    Argument Labels

    In Swift, you can specify the name of the parameter, and it may or may not be the same as the local variable that’ll hold the parameter value.

    For instance, when we take the sayHello(personA:personB) function above as an example, we can rewrite it with better readability by setting a custom argument label for each parameter.

    /// Let's rewrite this function for better readability:
    func sayHello(personA: String, personB: String) {
      print("Hello \(personA) and \(personB)!")
    }
    
    /// by using argument labels, we can rewrite it as:
    func sayHello(to personA: String, and personB: String) {
      print("Hello \(personA) and \(personB)!")
    }

    In the rewritten example, calling the sayHello function would be more natural as its become closer to how we say it in the English language:

    /// from calling the one without custom argument labels
    sayHello(personA: "Alice", personB: "Bob")
    // prints "Hello Alice and Bob!"
    
    /// to calling the one with custom argument labels
    sayHello(to: "Alice", and: "Bob")
    // prints "Hello Alice and Bob!"

    Under the hood, both sayHello functions work the same. In both cases, the function accepts two String parameters and store them into personA and personB variables as locally-scoped properties.

    Setting custom argument labels helps with readability, so make sure to use this amazing Swift language feature.

    When you don’t want the function to have an argument label upon call you can do so by using the underscore _ symbol as the argument label.

    func add(_ x: Int, _ y: Int) -> Int {
      return x + y
    }
    
    /// calling the add function above would no longer have argument labels:
    let sum = add(2, 3)
    print(sum) // prints 5

    Return Type

    Every function in Swift has a return type. You can specify the return type of the function by using the return arrow -> operator.

    // A function that returns an `Int` number
    func add(x: Int, y: Int) -> Int { ... }
    
    // A function that returns a `String`
    func sayHello(name: String) -> String { ... }
    
    // When you don't specify a return type, Swift will implicitly
    // identify it to return a special value of type Void.
    func print(_ s: String) { ... }

    When you don’t specify a return type, Swift will treat the function to return a value of Void type, which is simply an empty tuple ().

    Both of these examples are the same:

    func print(_ s: String) { ... }
    func print(_ s: String) -> Void { ... }

    Function Signature and Body

    The entire function declaration from the func keyword, the name of the function, the parameters it accepts, and its return type is what’s called a function signature; while the code block inside the curly braces { ... } is what’s called the body of the function.

    // This is the function signature:
    func sayHello(name: String) -> String
    
    // while this is the function body:
    { return "Hello \(name)!" }

    The signature describes what a function is:

    1. what its name is
    2. what parameters it accepts
    3. what its return type would be

    While the body describes what work is done in sequential order of the code within it.

    Calling a Function

    As you may have noticed on previous examples above, to call a function, we can simply write its name and provide all parameters that it needs.

    /// For example:
    func add(x: Int, y: Int) -> Int {
      return x + y
    }
    
    /// we can "call" the add function by:
    let sum = add(x: 2, y: 3)
    print(sum) // prints 5

    Hope you get to learn the basic concepts of the use of functions.

    Up next we’ll discuss closures, and functions that accept functions as parameter called higher-order functions.

    That’s all for now, cheers!



    Get started for free

    Join over 2,000+ students actively learning with CodeWithChris