Swift Class Extension Explained

In this Swift tutorial, I’ll show you how to add new functionality to existing Swift classes using class extensions. It’s a powerful feature in Swift that lets you add your own methods or computed properties to already-defined classes, making them more versatile.

Let’s start with a very simple example.

Creating a Simple Extension

In Swift, creating an extension is a straightforward task. You can easily add new functionality to an existing class, struct, or enum. In this section, I’ll demonstrate how to create a simple extension for a String class that adds a method to reverse the characters of a string.

Example 1: Extending the String Class

// Define the extension
extension String {
    func reverseCharacters() -> String {
        return String(self.reversed())
    }
}

// Usage
let originalString = "Hello, World!"
let reversedString = originalString.reverseCharacters()
print(reversedString)  // Output: !dlroW ,olleH

Explanation of the code above:

  1. I first define an extension for the String class using the extension keyword, followed by the name of the class being extended.
  2. Inside the extension block, I define a new method called reverseCharacters(). This method returns a new string with the characters reversed.
  3. Finally, I created a String object called originalString, and call the reverseCharacters() method on it to get and print the reversed string.

With just a few lines of code, you’ve seen how you can create a simple extension to add new functionality to an existing class. This is a fundamental aspect of Swift programming, allowing for greater modularity and code reuse.

Example 2: Extending the Int Class

In this example, I’ll show you how to extend the Int class in Swift to include a new method that subtracts a given integer from the current integer.

// Extend the Int class in Swift
extension Int {
    func takeAway(a: Int) -> Int {
        return self - a
    }
}

// Usage
let originalNumber = 10
let result = originalNumber.takeAway(a: 4)
print(result)  // Output: 6

Explanation of the code above:

  1. I first define an extension for the Int class using the extension keyword, followed by the name of the class being extended.
  2. Inside the extension block, I define a new method called takeAway(a: Int) -> Int. This method takes one parameter a of type Int, and returns the result of subtracting a from the current instance of Int class.
  3. Finally, I create an Int object called originalNumber, and call the takeAway(a: Int) method on it to get and print the result of the subtraction operation.
  • Declare an object of String data type and add to it our own custom function,
  • Add our own function to an existing Int class in Swift.

Example 3: Multiple Extensions in the Same UIViewController Class

In the code below, I’ll show you how to use multiple extensions in the same UIViewController class in Swift.

I extend the String and Int classes to add new methods reverseCharacters and takeAway. Then, in the ViewController class, I use these new methods on a String and an Int object. This way, you can see how to add more functions to existing classes and use them in your code, all within a single UIViewController.

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Declare String value
        let originalString: String = "Hello, World!"
        
        // Declare Int value
        let originalNumber: Int = 10
        
        // Call the "reverseCharacters()" function we have extended the String class with:
        print("Reversed String: \(originalString.reverseCharacters())")
        
        // Call the "takeAway()" function we have extended the Int class with:
        print("10 take away 4 equals \(originalNumber.takeAway(a: 4))")
    }
 
}

// Extend the String class in Swift
extension String {
    func reverseCharacters() -> String {
        return String(self.reversed())
    }
}

// Extend the Int class in Swift
extension Int {
    func takeAway(a: Int) -> Int {
        return self - a
    }
}

Computed Properties in Extensions

In Swift, a powerful feature is the ability to add computed properties to existing classes through extensions. Unlike stored properties, which hold actual values, computed properties calculate a value based on other properties.

In this section, I’ll explain how you can add a computed property to a class using an extension. You will learn to create a ShoppingCart class and extend it to compute the total price of the items in the cart.

Let’s begin by defining a simple ShoppingCart class with an array to hold the prices of items added to the cart.

class ShoppingCart {
    var itemPrices: [Double] = []
}

Now, I’ll extend the ShoppingCart class to include a computed property that calculates the total price of the items.

extension ShoppingCart {
    var totalPrice: Double {
        var total: Double = 0
        for price in itemPrices {
            total += price
        }
        return total
    }
}

Explanation of the code above:

  1. I first create a ShoppingCart class with an array property itemPrices to hold the prices of the items.
  2. Next, I define an extension for the ShoppingCart class using the extension keyword.
  3. Inside the extension block, I define a new computed property called totalPrice.
  4. This totalPrice property iterates through the itemPrices array, adding up all the prices to calculate the total price.
  5. The totalPrice property then returns the total price of the items in the cart.

Usage:

let myCart = ShoppingCart()
myCart.itemPrices = [10.99, 20.99, 15.99]
print("Total Price: \(myCart.totalPrice)")  // Output: Total Price: 47.97

In the usage example above, I create a ShoppingCart object called myCart, add some item prices to the itemPrices array, and then access the totalPrice computed property to get and print the total price of the items in the cart.

Initializers in Extensions

In Swift, you can also add new initializers to existing classes through extensions. This is handy when you want to customize the initialization of a class without having access to its source code.

In this section, I’ll guide you on how to extend the ShoppingCart class from our previous example to include a new initializer. You will learn how to create an initializer in an extension that sets up our ShoppingCart with an initial set of item prices.

Alright, so let’s begin!

But first, let’s revisit our ShoppingCart class:

class ShoppingCart {
    var itemPrices: [Double] = []
}

Now, I’ll create an extension for the ShoppingCart class and add a new initializer that accepts an array of item prices.

extension ShoppingCart {
    convenience init(initialPrices: [Double]) {
        self.init()
        self.itemPrices = initialPrices
    }
}

Explanation of the code above:

  1. I start by creating an extension for the ShoppingCart class using the extension keyword.
  2. In the extension block, I define a new initializer using the convenience init keyword, followed by a parameter name initialPrices of type [Double] (an array of doubles).
  3. Inside the initializer, I call self.init() to ensure that the ShoppingCart class’s default initializer is called, setting up any necessary default values.
  4. Then, I set the itemPrices property of the ShoppingCart class to the initialPrices array passed to the initializer.

Usage:

let myCart = ShoppingCart(initialPrices: [10.99, 20.99, 15.99])
print("Item Prices: \(myCart.itemPrices)")  // Output: Item Prices: [10.99, 20.99, 15.99]

In the usage example, I create a new ShoppingCart object called myCart using the new initializer, passing an array of initial item prices. This initializes the myCart object with the given item prices, which are then printed to the console.

Conforming to Protocols

Protocols define a blueprint of methods, properties, and other requirements for a particular task or functionality. In Swift, you can use extensions to add protocol conformance to a class, struct, or enumeration. In this section, I’ll explain how you can extend the ShoppingCart class to conform to a protocol. You will learn to define a protocol that requires a method to calculate the total price, and then extend ShoppingCart to conform to this protocol.

Let’s start by defining the ShoppingCart class:

class ShoppingCart {
    var itemPrices: [Double] = []
}

Now, let’s create a protocol called TotalPriceCalculable:

protocol TotalPriceCalculable {
    func calculateTotalPrice() -> Double
}

The TotalPriceCalculable protocol defines a single method calculateTotalPrice, which any type can implement to calculate the total price of items.

Now, let’s extend the ShoppingCart class to conform to the TotalPriceCalculable protocol:

extension ShoppingCart: TotalPriceCalculable {
    func calculateTotalPrice() -> Double {
        var total: Double = 0
        for price in itemPrices {
            total += price
        }
        return total
    }
}

Explanation of the code above:

  1. I first define a ShoppingCart class with an array property itemPrices to hold the prices of the items.
  2. Then, I create a protocol named TotalPriceCalculable with a method signature for calculateTotalPrice.
  3. Next, I create an extension for the ShoppingCart class, specifying that it conforms to the TotalPriceCalculable protocol by placing a colon and the protocol name after the class name.
  4. Inside the extension block, I implement the calculateTotalPrice method as required by the TotalPriceCalculable protocol. This method iterates through the itemPrices array, summing up all the prices to calculate the total price, and then returns the total price.

Usage:

let myCart = ShoppingCart()
myCart.itemPrices = [10.99, 20.99, 15.99]
let totalPrice = myCart.calculateTotalPrice()
print("Total Price: \(totalPrice)")  // Output: Total Price: 47.97

In the usage example, I created a ShoppingCart object called myCart, add some item prices to the itemPrices array, and then call the calculateTotalPrice method to get and print the total price of the items in the cart.

Now, you’ve learned how to use extensions to conform to protocols, further extending the capabilities of the ShoppingCart class to adhere to a defined blueprint, making your code more structured and maintainable.

Extending Cocoa Touch Framework Classes

Cocoa Touch Framework is a core part of iOS development, providing essential classes for building iOS apps. Sometimes, you might need to add some functionality to these classes to better fit your needs. Swift’s extensions come in handy for this task.

In this section, I’ll explain how you can extend a Cocoa Touch Framework class, specifically UILabel, to add some custom functionality. You will learn to create an extension for UILabel to add a method that changes the text color based on the text’s content.

Let’s start by creating an extension for UILabel:

import UIKit

extension UILabel {
    func updateTextColor() {
        guard let text = self.text else {
            self.textColor = UIColor.black
            return
        }
        
        if text.contains("Error") {
            self.textColor = UIColor.red
        } else {
            self.textColor = UIColor.black
        }
    }
}

Explanation of the code above:

  1. I first imported the UIKit framework, which includes the UILabel class, among many others.
  2. Then, I create an extension for the UILabel class using the extension keyword.
  3. Inside the extension block, I define a new method called updateTextColor.
  4. This method first checks if the label has any text using the guard statement. If the text is nil, it sets the text color to black and exits the method.
  5. If there’s text, it checks if the text contains the word “Error” using the contains method on the text string. If so, it sets the text color to red. Otherwise, it sets the text color to black.

Usage:

let myLabel = UILabel()
myLabel.text = "Error: Something went wrong."
myLabel.updateTextColor()  // The text color will change to red

In the usage example, I create a UILabel object called myLabel, set its text to a string containing the word “Error”, and then call the updateTextColor method to update the text color to red.

Conclusion

I hope this tutorial has provided a clear understanding of how to extend existing Swift classes using class extensions. It’s a powerful way to add new functionality and make the classes work according to your specific needs. As you’ve seen, with just a few lines of code, you can define and use extensions to enrich the functionality of existing Swift types right within a UIViewController.

For further exploration and to dive deeper into Swift programming, I invite you to check out other Swift code examples on my blog. There, you’ll find a variety of examples that can help you become more proficient in Swift programming. Happy coding!

 

Leave a Reply

Your email address will not be published. Required fields are marked *