< Return to all blogs
Swift Classes August 2017: Classes, Subclasses, and Protocols
The basics of classes and subclasses as well as a detailed tutorial on setting up your own custom protocols and delegates.
Swift Classes August 2017: Classes, Subclasses, and Protocols
Classes
In this post, I will cover the basics of Swift classes, subclasses, and their protocols/delegates. Classes are a foundational piece of computer science and software development. They allow developers to create instances of a certain type of object with pre-defined methods (functions) and instance variables (properties). For example, a class might be a car
with an instance variable: wheels = 4
and a method: driveForward()
. Here is what it would look like in Swift 3:
// Declaration
class Car {
// Immutable and only accessible within this class
// No initial value
private let wheels: Int
// Mutable and accessible outside of this class
// Initial value 1
public var passengers: Int = 1
// Called when a new instance of "Car" is created
init(wheels: Int) {
self.wheels = wheels // Set instance variable
}
// Can be called on an instance of "Car"
public func driveForward() -> void {
...
}
}
// Usage
let porche: Car = Car(wheels: 4)
print(porche.passengers) // 1
porche.driveForward() // ...
All cars have wheels and they all the ability to drive forward — that is why these become part of the class. Classes are a way of standardizing objects that have similar properties, just different values. This method of creating classes is what allows for modular-code, an essential aspect of computing and engineering.
Subclasses
Subclasses are a way of building on top of existing classes. For example, if we continue with our example of the class Car
, a subclass could be Tesla
. They share very similar properties, but Tesla’s have key features that set them apart from cars. Tesla
would inherit all the essential properties and methods from Car
, but add on its own special components. Here is an example:
class Tesla: Car { // Inherit "Car"
public func charge() -> void {
...
}
}
Any instance of Tesla would still have the same constructor and properties like wheels
and driveForward()
, but would include a new method charge()
unique to instances of type Tesla
.
Protocols & Delegates
Protocols are a way of enforcing a parent or other class conforms to a set of methods. It’s a somewhat complicated topic and it makes the most sense once you’ve worked with Swift for a little bit, but here are some easy example.
The easiest example of a protocol is when you create a sublcass of a UIViewController
. By subclassing, you are adding on top of the existing class UIViewController
. You are also given the option to override certain functions like viewDidLoad()
and viewDidLayoutSubviews()
. These methods are optional protocols in UIViewController
made available to you because the delegate — what is responsible for satisfying the protocols — is set to the new subclass.
That’s all very confusing, but here’s a step by step on how they work and how to create your own class with protocols. It might clear up your confusion.
-
Create a class that has an event listener.
class SomeClass { private let button: UIButton = UIButton() ... private func buttonPressed() { print("I was pressed") } }
This function,
buttonPressed()
, will be run every time the button is pressed. This begs the question, how will theUIViewController
that contains an instance ofSomeClass
detect when the button was pressed? It can create an interval timer that checks every 1/10 of a second to see if the button state has changed, but that’s neither efficient nor practical. Instead we must use a protocol.
-
Create a protocol.
protocol SomeDelegate: class { func buttonWasPressed(someValue: Int) // Passes back a parameter } @objc protocol SomeDelegate: class { @objc optional func buttonWasReleased() // Optional protocol }
Notice the first protocol passes back a value. This is useful when you want the parent to be able to listen and track when a specific value has changed. You can simply trigger the protocol every time the value is changed and pass the value as the parameter. The second protocol example doesn’t take a paramter, but it is optional. This means that the parent class doesn’t need to include
buttonWasReleased()
in order to conform to the protocolSomeDelegate
. Notice the use of the@objc
tags.
-
Establish the protocol as an instance variable named
delegate
.class SomeClass { weak var delegate: SomeDelegate? }
-
Call the appropriate protocol method in your class to trigger the listener.
class SomeClass { ... private func buttonPressed() { print("I was pressed") self.delegate.buttonWasPressed(someValue: 1) // For optional protocols self.delegate?.buttonWasReleased?() // Optional so don't force otherwise app will crash } }
This new line triggers the protocol method
buttonWasPressed
and passes the value1
up to the parent. Now we’ll cover how to actually use this in your class.
-
In your
UIViewController
subclass, add the protocol as a class to conform to.class SomeViewController: UIViewController, SomeDelegate { ... }
-
Connect or create the instance of the class and attach
self
as the delegate. This will tell the protocol that this current class will conform to the protocol.class SomeViewController: UIViewController, SomeDelegate { override func viewDidLoad() { super.viewDidLoad() let example: SomeClass = SomeClass() example.delegate = self } }
-
Add the protocol as a function. If everything was set up correctly, the method should auto-complete.
class SomeViewController: UIViewController, SomeDelegate { ... func buttonWasPressed(someValue: Int) { print("Button was pressed with value: \(someValue)") } }
That’s it! Now every time the function buttonPressed()
is run, it will run buttonWasPressed()
in SomeViewController
and pass a value. This is a great way of communicating between a child and parent when some event is triggered by the user.
Hope this tutorial helped! It’s been a few months since I did any iOS dev (got caught up in a lot of web dev because of work) so I hope my explanations and code were clear and clean.
Posted in iOS Development with Swift, Tutorial