Extensions in Swift

Extend someone else’s work — no danger

Extensions enable you to tidy and create great code in Swift. Let’s get started!

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

  • Be able to produce a “Hello, World!” iOS application (guide HERE)
  • Knowledge of classes, structures and enums (guide HERE)

Terminology

class: An object defined in Swift, using pass by reference semantics (reference)

enum: A Type for a group of related values

extensions: Extensions add new functionality to a class, struct, enum or protocol

override: The process in which a subclass changes a method, property or type in the parent class

private: A level of access control that restricts the use of an entity to the enclosing declaration, and extensions of that declaration that are in the same file

struct: A value type to encapsulate complex data types

Extensions: What they are, and what they aren’t

So the idea is that you have an existing class, structure, enumeration (click the link for an explanation) and you need to extend the functionality you should be reading this article.

Now there are limitations on extensions, but that is covered in the next part of this article.

The view controller example

One use of extensions is where a view controller with an embedded table view, and you wish to separate out the code for the data source and the delegate. One way of doing this is shown below:

Now you could choose to have the extensions in separate files, this would be absolutely fine.

As a ViewController is a class, this is an example of extending a class.

Extending a struct

Any struct can be extended. A simple example of this follows:

once again this adds new functionality. Which is nice.

However instead of using a function to calculate the area we can use a computed property to do the same.

which demonstrates the flexibility of these extensions we are adding in these examples.

Adding functionality through an extension

Extensions can be used to add functionality to struct or a class, even if you don’t own the class. Here is an example of how Date can be extended (and is included in the Repo link below):

extension Date {
var dateString: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy"
return dateFormatter.string(from: self)
}
}

which can be called from a date (and for example we can have the present day printed with this format

let date = Date()
print (date.dateString)

Using extensions to make an existing type conform to a protocol

This can be useful when you wish to use dependency injection, and replace a concrete class with a mocked version.

Now this might be quite tricky as you may not own the original class. Now in this case, you might choose to use an extension to make the original class conform to a protocol. In this case I will demonstrate with a use of URLSession as follows:

So we can create our protocol which is URLSessionProtocol as declared below

protocol URLSessionProtocol {
fun dataTask(with request: URLRequest,
completionHandler: @escaping (Data?, URLResponse?, Error?)
-> Void) -> URLSessionDataTask
}

which we will make both our mock and the original URLSession conform to. The mock is as follows

But then we need to make the original class conform. Here is the extension:

extension URLSession: URLSessionProtocol {}

and where we wish to use either URLSession we use the protocol like:

fileprivate let session: URLSessionProtocol

Limits to extensions

Extensions cannot contain stored properties. That means the following is not compilable code.

struct Bottle { }extension Bottle {
var name: String // Error: Extensions cannot contain stored properties
}

Using getters and setters we can compute properties in extensions, enabling us to provide great extensions with exciting functionality.

You can’t prevent another developer from adding an extension to a class. Much like you can conform to a protocol, there is no harm in doing so as you can only extend functionality in a class rather than changing it (and perhaps breaking code), and if you want to stop extensions for your classes (or indeed protect protocols) mark them with private.

Conclusion…

Extensions in Swift can (in short, and not all of these have been covered in the previous article)

  • Add computed properties
  • Provide initilizers
  • Define subscripts
  • Create nested types
  • Make an existing type conform to a protocol

Repo

Here is the repo with the relevant code:

https://github.com/stevencurtis/extenstionsswift

Want to get in contact? Try the link here:

https://twitter.com/stevenpcurtis

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store