Extensions In Swift - how to use them?

Extensions In Swift

(Last Updated On: September 25, 2021)

It’s been a long time since I have written a blog. But today, a post on Stackoverflow motivated me so much to write a post on the use of Extensions In Swift. Why? Because I have seen many beginners totally neglecting extensions and have no idea how useful they can be.

So I will try to list the points here today and discuss it one by one what functionalities do Extensions provide us:

  1. You may use Extensions for conforming to a protocol.
  2. Define instance methods and type methods
  3. Provide New Initializers.
  4. Define Subscripts
  5. Define and use new nested types.
  6. Add computed instance properties and computed type properties

NOTE:

Extensions can add new functionalities to a type, But they can not override an existing property.

Now let’s discuss the above points one by one.

Extension For Conforming to A Protocol

When using a UITableView, we always make our ViewController conform to UITableViewDataSource And UITableViewDelegate protocol methods.

class YouViewController : UIViewController, UITableViewDataSource, UITableViewDelegate { 
    // your viewController setup code
    // your table view callback methods
}

And if you are using let’s say, UICollectionView also in the same controller, your class declaration will look something like this now:

class YouViewController : UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    // your viewController setup code
    // your table view callback methods
    // your collection view callback methods
}

Do you see what’s happening above? The more and more functionalities you are adding, your class has to conform to the protocols and then you will have to write all the callback methods in the same class which make the code hard to read. What’s the solution? Glad you asked. Extensions.

class YourViewController : UIViewController { 
    // your viewController setup code
}

extension YourViewController : UITableViewDataSource, UITableViewDelegate { 
    // your table view callback methods
}

extension YourViewController : UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 
    // your collection view callback methods
}

This way you can make your code easy to read using Extensions In Swift. If you were not following this pattern till now, I would suggest better start following it.

Extensions on Instance Method or Type Methods

Instance Method is the method which you call on an instance of a type.

For eg: The code below declares a class named ArithmeticOperations and then declares a function inside it named add(), which takes multiple Integers as input and then returns the sum of all the Integers.

NOTE: I have used Variadic Parameters in defining the add function, If you don’t know about it, read this post and learn within a minute. Variadic Parameters in Swift

import Foundation

class ArithmeticOperations : NSObject {
    
    // Instance Method
    func add(_ num : Int...) -> Int { // variadic parameter
        return num.reduce(0, +) // adds all the numbers in num array and returns the sum.
    }
    
    // Type Method
    class func printAnything() {
        print("Aabara ka dabara")
    }
}

//creating instance and then calling the method
let sumObj = ArithmeticOperations()
print(sumObj.add(0,1,2,3,4,5,6,7,8,9)) // 45


// calling the type method

ArithmeticOperations.printAnything() // Aabara ka dabara

As you can see above, the instance method can only be called by creating an instance of it first and then calling the function.

Whereas, for calling the type method, we can directly do it without creating an instance.

Now that you have understood what instance method and type method is, let’s come back to how we can use Extensions in it.

class ArithmeticOperations : NSObject {
    func add(_ num : Int...) -> Int {
        return num.reduce(0, +)
    }
    class func printAnything() {
        print("Aabara ka dabara")
    }
}

//MARK: Subtraction
extension ArithmeticOperations {
    func subtract(_ num : Int...) -> Int {
         return num.reduce(0, -)
    }
}

let subtractObj = ArithmeticOperations()
print(subtractObj.subtract(10,9,8,7,6,5,4,3,2,1)) // -55

In the above code, we have created an extension for the same class ArithmeticOperations for and added a Subtraction function in it. And now we can use the subtraction method same as the addition method anywhere in the project.

Extensions come really handy when you have to work on pre-defined methods.

Let’s say you want to extend the Int type and add a function to it which returns the cube of a number.

extension Int {
    func cube() -> Int {
        return self*self*self
    }
}
print(3.cube()) // 27

Easy right?

Add New Initializers Using Extension

Extensions can add new initializers to existing types. This enables you to extend other types to accept your own custom types as initializer parameters, or to provide additional initialization options that were not included as part of the type’s original implementation.

Extensions can add new convenience initializers to a class, but they can’t add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.

Apple

Below is an example of how you can create your own initializer in extensions.

extension UIColor {
    convenience init<T: BinaryInteger>(r: T, g: T, b: T, a: T = 255) {
        self.init(red: .init(r)/255, green: .init(g)/255, blue: .init(b)/255, alpha: .init(a)/255)
    }
    convenience init<T: BinaryFloatingPoint>(r: T, g: T, b: T, a: T = 1.0) {
        self.init(red: .init(r), green: .init(g), blue: .init(b), alpha: .init(a))
    }
}

let green1 = UIColor(r: 0, g: 255, b: 0, a: 255)  // r 0,0 g 1,0 b 0,0 a 1,0
let green2 = UIColor(r: 0, g: 1.0, b: 0, a: 1.0)  // r 0,0 g 1,0 b 0,0 a 1,0

let red1 = UIColor(r: 255, g: 0, b: 0)  // r 1,0 g 0,0 b 0,0 a 1,0
let red2 = UIColor(r: 1.0, g: 0, b: 0)  // r 1,0 g 0,0 b 0,0 a 1,0

Other than the above, you can also use extensions for Subscripts, Nested Types and Computed Properties

To learn more about it you can follow the official Swift Doc link here: Declaring Subscript, Nested Types and Computed Properties in Extensions in Swift

If any queries, let me know in the comments. Thanks for reading.

Leave a Comment