1. Introduction

  • Extensions add new functionality to an existing class, structure, enumeration, or protocol type.
  • This includes the ability to extend types for which you do not have access to the original source code.
  • Declare extensions with the extension keyword
  • Format of Extension
extension SomeType {
    // new functionality 
}
  • An extension can extend an existing type to make it adopt one or more protocols.
  • To add protocol conformance, you write the protocol names the same way as you write them for a class or structure:
extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol 
}

1.1 Computed Properties

  • Extensions can add computed instance properties and computed type properties to existing types.
extension String {
    
    func replace(target: String, withString: String) -> String {
        return self.replacingOccurrences(of: target, with: withString)
    }
}

let newString = "the old bike".replace(target: "old", withString: "new")
print(newString)

// prints : the new bike

1.2 Initializers

  • 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.
struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
}
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
                          size: Size(width: 5.0, height: 5.0))
print(memberwiseRect.origin, memberwiseRect.size)

extension Rect {
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
                      size: Size(width: 3.0, height: 3.0))
print(centerRect.origin, centerRect.size)

/* prints:
Point(x: 2.0, y: 2.0) Size(width: 5.0, height: 5.0)
Point(x: 2.5, y: 2.5) Size(width: 3.0, height: 3.0)
*/

1.3 Methods

  • Extensions can add new instance methods and type methods to existing types.
extension Int {
    func reps(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}
3.reps {
    print("This is repetitive text")
}

/* prints: 
This is repetitive text
This is repetitive text
This is repetitive text
*/

1.4 Mutating Instance Methods

  • Instance methods added with an extension can also modify (or mutate) the instance itself.
  • Structure and enumeration methods that modify self or its properties must mark the instance method as mutating, just like mutating methods from an original implementation.
extension Int {
    mutating func square() {
        self = self * self
    }
}
var someInt = 3
someInt.square()
print(someInt)

// prints: 9

1.5 Subscripts

  • Extensions can add new subscripts to an existing type.
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}

print(746381295[0], 746381295[1])

// prints: 5 9

1.6 Nested Types

  • Extensions can add new nested types to existing classes, structures, and enumerations.
extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
}
func printIntegerKinds(_ numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .negative:
            print("- ", terminator: "")
        case .zero:
            print("0 ", terminator: "")
        case .positive:
            print("+ ", terminator: "")
        }
    }
    print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])

//prints: + + - 0 - 0 + 

You can download the swift playground of all above examples from Here