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:
- I first define an extension for the
Stringclass using theextensionkeyword, followed by the name of the class being extended. - Inside the extension block, I define a new method called
reverseCharacters(). This method returns a new string with the characters reversed. - Finally, I created a
Stringobject calledoriginalString, and call thereverseCharacters()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:
- I first define an extension for the
Intclass using theextensionkeyword, followed by the name of the class being extended. - Inside the extension block, I define a new method called
takeAway(a: Int) -> Int. This method takes one parameteraof typeInt, and returns the result of subtractingafrom the current instance ofIntclass. - Finally, I create an
Intobject calledoriginalNumber, and call thetakeAway(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:
- I first create a
ShoppingCartclass with an array propertyitemPricesto hold the prices of the items. - Next, I define an extension for the
ShoppingCartclass using theextensionkeyword. - Inside the extension block, I define a new computed property called
totalPrice. - This
totalPriceproperty iterates through theitemPricesarray, adding up all the prices to calculate the total price. - The
totalPriceproperty 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:
- I start by creating an extension for the
ShoppingCartclass using theextensionkeyword. - In the extension block, I define a new initializer using the
convenience initkeyword, followed by a parameter nameinitialPricesof type[Double](an array of doubles). - Inside the initializer, I call
self.init()to ensure that theShoppingCartclass’s default initializer is called, setting up any necessary default values. - Then, I set the
itemPricesproperty of theShoppingCartclass to theinitialPricesarray 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:
- I first define a
ShoppingCartclass with an array propertyitemPricesto hold the prices of the items. - Then, I create a protocol named
TotalPriceCalculablewith a method signature forcalculateTotalPrice. - Next, I create an extension for the
ShoppingCartclass, specifying that it conforms to theTotalPriceCalculableprotocol by placing a colon and the protocol name after the class name. - Inside the extension block, I implement the
calculateTotalPricemethod as required by theTotalPriceCalculableprotocol. This method iterates through theitemPricesarray, 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:
- I first imported the
UIKitframework, which includes theUILabelclass, among many others. - Then, I create an extension for the
UILabelclass using theextensionkeyword. - Inside the extension block, I define a new method called
updateTextColor. - This method first checks if the label has any text using the
guardstatement. If the text isnil, it sets the text color to black and exits the method. - If there’s text, it checks if the text contains the word “Error” using the
containsmethod 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!