Introduction To Swift Programming (Part 4): Advanced Swift Concepts

Unlocking Advanced Swift Concepts like Optionals, Closures, and Properties for Cleaner and More Efficient Code

Hina Khan
6 min readOct 15, 2023
Image By Author on Canva

Swift is a powerful programming language, known for its simplicity and performance.

Before we dive into advanced Swift concepts, let’s take a moment to recap the fantastic journey we’ve had in the ‘Introduction to Swift Programming.’

Part 1: Exploring Xcode Playgrounds
Part 2: Getting Started with Xcode
Part 3: Mastering the Swift Basics

In this article, we will dive into some of the more advanced concepts of Swift, and will provide a comprehensive and well-structured overview of advanced Swift concepts including Optionals, Closures, and Properties.

Understanding these concepts can greatly enhance your proficiency in Swift and your ability to write clean, efficient code.

1. Optionals:

Optionals provide a way to declare variables that can either hold a value or be nil.

Declaring Optional Variables:

To denote an optional variable, add a question mark (?) to its type declaration.

var maybeString: String? = "Hello, Swift" // An optional string
var notAnOptional: String = "Hello, World" // A non-optional string

Unwrapping Optionals:

To access the value of an optional variable, we must unwrap it using an exclamation mark (!).

let maybeString: String? = "Hello, Swift"
let unwrappedString: String = maybeString! // Using the exclamation mark to force unwrap
print(unwrappedString) // "Hello, Swift"

NOTE: If we attempt to unwrap an optional that is nil, a runtime error will occur, alerting us to the issue. This approach helps ensure the robustness of our programs.

2. Closures:

Closures are Swift’s concise way of defining functions. They play a crucial role in making Swift code more efficient and expressive.

Functions in Swift: A Familiar Starting Point

Before delving into closures, let’s begin by exploring the concept of functions in Swift.

Functions are named blocks of code defined using the func keyword. Swift treats functions as first-class citizens, meaning they can be assigned to variables or constants.

Here’s a simple example:

// Define a simple function called performMagic
func performMagic(spell: String) -> String {
return spell
}


// Call the function and assign its result to a variable
let magicFunction = performMagic
let result = magicFunction("disappear")

// Print the result
print(result) // Output: "disappear"

In this function example:

  1. We have a function performMagic that takes a spell and gives it back as the result.
  2. Then, we assigns the function performMagic to a variable magicFunction. This is possible in Swift because functions are first-class citizens, which means they can be assigned to variables or constants just like any other value.
  3. Finally, we call performMagic with the spell "Disappear" and print the result.

Now, Let’s Explore Closures

Swift introduces closures as a more concise way of defining functions. Closures are like nameless blocks of code that can be assigned to variables or constants, adding flexibility to your code.

Here’s a closure example:

// Now, let's define the same logic using a closure
let newMagicFunction: (String) -> String = { spell in
return spell
}

// Call the closure and assign its result to another variable
let closureResult = newMagicFunction("Reappear")

// Print the closure result
print(closureResult) // Output: "Reappear"

In this closure example:

  1. We create a closure called newMagicFunction which works just like performMagic. It takes a spell and returns it.
  2. The closure is assigned to a variable with the type annotation (String) -> String, which indicates it's a closure that takes a String parameter and returns a String.
  3. We call the newMagicFunction closure with the spell "Reappear" and and assign the result to the variable closureResult.
  4. Print the result.

Closures provide flexibility in function declaration and can be advantageous in scenarios where clarity are essential.

The Difference: Functions vs. Closures

Functions are named blocks of code we define with the func keyword,

while closures are anonymous(nameless) blocks of code that can be assigned to variables or constants.

Closures are like function ingredients we can use whenever we need them, adding flexibility to our code.

3. Properties:

Properties associate values with a particular class, structure, or enumeration.

They can be either stored properties or computed properties.

Stored Properties:

Stored properties store values within a structure or class.

Note: These values are stored as part of the structure or class.

struct Animal {
var name: String
var heightInInches: Double
}

Here, we define a struct called Animal with stored properties name and heightInInches.

These properties are referred to as “stored” properties because they directly store values within the struct.

The Challenge of Redundancy: Avoiding Duplication

Now, consider a scenario where we also want to store the height of the animal in centimeters (heightInCentimeters).

If we were to add it as another stored property, it would lead to redundancy.………………Why?

Because the height in centimeters can be derived from the height in inches. Storing both independently would require manually updating both properties whenever one changes, introducing room for error.

Swift provides a brilliant solution for this: computed properties.

Computed Properties:

Computed properties allow us to perform calculations and return a value dynamically based on other properties within a Structure.

It can have custom getter and setter methods.

Computed Properties:

In our case, here’s how we define a computed property for heightInCentimeters based on heightInIncheswithin the Animal struct:

struct Animal {
var name: String
var heightInInches: Double

var heightInCentimeters: Double {
get {
return heightInInches * 2.54
}
set(newHeightInCentimeters) {
heightInInches = newHeightInCentimeters / 2.54
}
}
}

What's Happening Here:

In this updated struct:

  1. We’ve introduced a computed property named heightInCentimeters.
  2. The get block calculates heightInCentimeters by multiplying the value inheightInInches by the conversion factor, which is 2.54.
  3. The set block allows us to update heightInCentimeters. When we set a new value for heightInCentimeters, it automatically adjusts the value in heightInInches accordingly.

Therefore, by using a computed property, we’ve created a dynamic relationship between heightInInches and heightInCentimeters. When we access or modify heightInCentimeters, Swift automatically performs the necessary conversions.

Practical Usage Of Computed Properties in an example:

Now, let’s put our Animal struct to use with a practical example:

var myDog = Animal(
name: "Buddy",
heightInInches: 20.0
)

print(myDog.name) // Buddy
print(myDog.heightInInches) // 20.0
print(myDog.heightInCentimeters) // 50.8 (dynamically calculated from heightInInches)


myDog.heightInCentimeters = 30.48 // Setting height in centimeters


// Updated Height in Inches:
print(myDog.heightInInches) // 12.0
print(myDog.heightInCentimeters) // 30.48

In this example:

  • We create a myDog instance with a name "Buddy" and an initial height of 20.0inches.
  • We print out the dog’s name and initial height in both inches and centimeters. ( The height in centimeters 50.8cmis dynamically calculated based on the height in inches. )
  • We then set the height of the dog in centimeters to 30.48 cm using the heightInCentimeters computed property. This triggers a dynamic update of the heightInInches property, which is now 12.0 inches (because 30.48 cm is equivalent to 12.0 inches).
  • Finally, we print the updated height in both inches and centimeters, showing how the computed property maintains data consistency.

Computed properties is particularly useful in scenarios such as computer graphics, where values need to be synchronized.

Conclusion:

Mastering advanced Swift concepts like Optionals, Closures, and Properties empower you to write cleaner, more efficient, and robust code.

Swift’s elegant syntax and advanced capabilities make it a language worth exploring and mastering. So, continue your journey in Swift programming, and remember that practice and exploration are key to becoming a proficient Swift developer.

Happy coding!

Follow Up Reading:

For details on more advanced Swift programming visit the official links below according to topic: Closures, Classes and Structures, Properties

Liked this article?
Give claps and show your support.

Connect with me on social media for more tips, tutorials, and updates:

--

--

Hina Khan

Software Engineer— Flutter Expert | SwiftUI | Machine Learning Enthusiast