Skip to main content

Swift Return Values

Introduction

When you call a function in Swift, it can do more than just perform actions—it can also give you back information. This giving back of information is called "returning a value." Understanding how functions return values is essential for building useful applications where different parts of your code need to communicate and share data.

In this lesson, we'll explore how Swift functions return values, how to specify return types, and how to effectively use returned values in your code.

Understanding Return Values

A return value is the output of a function that gets passed back to the code that called it. When a function completes its task, it can send back a result using the return keyword.

Basic Syntax for Functions with Return Values

swift
func functionName(parameters) -> ReturnType {
// Function code
return valueToReturn
}

The arrow -> followed by a type indicates that the function returns a value of that type.

Simple Examples of Return Values

Let's start with a basic example of a function that returns a value:

swift
func add(a: Int, b: Int) -> Int {
return a + b
}

// Using the function
let sum = add(a: 5, b: 3)
print("The sum is: \(sum)")
// Output: The sum is: 8

In this example:

  • The function add takes two integers as parameters
  • It returns an integer (specified by -> Int)
  • The return keyword sends the result back
  • We store the returned value in the sum variable

Return Types in Swift

Swift supports returning various types:

Returning Primitive Types

swift
// Return an integer
func calculateAge(birthYear: Int) -> Int {
let currentYear = 2023
return currentYear - birthYear
}

// Return a string
func greet(name: String) -> String {
return "Hello, \(name)!"
}

// Return a boolean
func isEven(number: Int) -> Bool {
return number % 2 == 0
}

let age = calculateAge(birthYear: 1990)
print(age) // Output: 33

let greeting = greet(name: "Swift Learner")
print(greeting) // Output: Hello, Swift Learner!

let checkEven = isEven(number: 7)
print("Is 7 even? \(checkEven)") // Output: Is 7 even? false

Returning Collections

Functions can also return collections like arrays, dictionaries, and sets:

swift
// Returning an array
func generateFibonacciSequence(count: Int) -> [Int] {
var sequence = [0, 1]

while sequence.count < count {
let nextNumber = sequence[sequence.count - 1] + sequence[sequence.count - 2]
sequence.append(nextNumber)
}

return sequence
}

let fibNumbers = generateFibonacciSequence(count: 8)
print(fibNumbers)
// Output: [0, 1, 1, 2, 3, 5, 8, 13]

// Returning a dictionary
func createUserProfile(name: String, age: Int) -> [String: Any] {
return [
"name": name,
"age": age,
"createdAt": Date()
]
}

let user = createUserProfile(name: "Alex", age: 25)
print("User profile: \(user)")
// Output: User profile: ["name": "Alex", "age": 25, "createdAt": 2023-08-15 10:30:00 +0000]

Implicit Returns

For single-expression functions, Swift allows you to omit the return keyword:

swift
// With return keyword
func multiply(a: Int, b: Int) -> Int {
return a * b
}

// With implicit return (no return keyword needed)
func multiply2(a: Int, b: Int) -> Int {
a * b
}

print(multiply(a: 4, b: 5)) // Output: 20
print(multiply2(a: 4, b: 5)) // Output: 20 (same result)

This is especially useful for short, concise functions.

Optional Return Types

Sometimes, a function might not always be able to return a value. In such cases, we can use optional return types:

swift
func divide(a: Double, b: Double) -> Double? {
if b == 0 {
return nil // Cannot divide by zero
}
return a / b
}

if let result = divide(a: 10, b: 2) {
print("Result: \(result)") // Output: Result: 5.0
} else {
print("Division not possible")
}

if let result = divide(a: 10, b: 0) {
print("Result: \(result)")
} else {
print("Division not possible") // Output: Division not possible
}

The Double? return type indicates that the function returns either a Double or nil.

Multiple Return Values Using Tuples

Swift allows functions to return multiple values packaged as a tuple:

swift
func getStatistics(numbers: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = numbers[0]
var max = numbers[0]
var sum = 0

for number in numbers {
if number < min {
min = number
}
if number > max {
max = number
}
sum += number
}

return (min, max, sum)
}

let stats = getStatistics(numbers: [5, 3, 9, 1, 7])
print("Minimum: \(stats.min)") // Output: Minimum: 1
print("Maximum: \(stats.max)") // Output: Maximum: 9
print("Sum: \(stats.sum)") // Output: Sum: 25

// You can also access by index, but using names is clearer
print("Min value: \(stats.0)") // Output: Min value: 1

Real-World Applications

Let's explore some practical examples of functions with return values:

Calculator Application

swift
func performOperation(a: Double, b: Double, operation: String) -> Double? {
switch operation {
case "+":
return a + b
case "-":
return a - b
case "*":
return a * b
case "/":
if b == 0 {
return nil
}
return a / b
default:
return nil
}
}

// Using the calculator
let operationResult = performOperation(a: 15.5, b: 7.2, operation: "+")
if let result = operationResult {
print("Result: \(result)") // Output: Result: 22.7
} else {
print("Invalid operation")
}

User Authentication

swift
enum AuthenticationError {
case invalidUsername
case invalidPassword
case serverError
}

func authenticate(username: String, password: String) -> Result<String, AuthenticationError> {
// Check if username exists (simplified example)
if username != "user123" {
return .failure(.invalidUsername)
}

// Check if password is correct
if password != "securePass" {
return .failure(.invalidPassword)
}

// Generate authentication token (in real app, this would be more complex)
let token = "AUTH_TOKEN_\(username)_\(Date().timeIntervalSince1970)"
return .success(token)
}

// Using the authentication function
let authResult = authenticate(username: "user123", password: "securePass")

switch authResult {
case .success(let token):
print("Authentication successful. Token: \(token)")
case .failure(let error):
switch error {
case .invalidUsername:
print("Error: Username does not exist")
case .invalidPassword:
print("Error: Incorrect password")
case .serverError:
print("Error: Server issue. Try again later")
}
}

Best Practices for Return Values

  1. Be clear about return types: Always explicitly define what your function returns.
  2. Use meaningful names: Name your functions to indicate what they return (e.g., calculateArea, fetchUserData).
  3. Consider optionals: If a function might fail to produce a value, use optional return types.
  4. Use tuples for multiple returns: When you need to return multiple related values.
  5. Be consistent: If similar functions return values, they should all follow the same pattern.

Summary

Return values are a fundamental concept in Swift programming that allow functions to communicate results back to the calling code. We've explored:

  • How to define functions with return types
  • Returning different types of data (primitives, collections, optionals)
  • Using implicit returns for concise functions
  • Returning multiple values with tuples
  • Real-world applications of return values

Understanding return values enables you to write more modular, reusable code where different parts of your application can exchange information efficiently.

Exercises

  1. Write a function that takes an array of integers and returns the average as a Double.
  2. Create a function that takes a string and returns a tuple containing the count of vowels and consonants.
  3. Write a function that takes two dates and returns the number of days between them.
  4. Create a shopping cart function that calculates the total price, including tax, and returns both the subtotal and final price.
  5. Build a password validator function that returns either a success message or a specific error message explaining why the password is invalid.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)