Getting to Know Enum, Struct and Class Types in Swift
Learn all about enums, structs, and classes in Swift, including value vs reference semantics, dynamic member lookup, and protocol conformance. By Adam Rush.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Getting to Know Enum, Struct and Class Types in Swift
35 mins
- It’s All About Those Types
- Shapes With Scalable Vector Graphics (SVG)
- Getting Started
- Using Enums
- CaseIterable
- Associated Values
- Protocols and Methods With an Enum
- Initializers With an Enum
- Namespaces With Enum
- Taking Stock of Enums
- Using Structs
- Dynamic Member Lookup
- Value vs. Reference Types
- Rectangle Model
- Show Me Some SVG
- Using Classes
- Why Even Use a Class?
- Implementing Computed Properties
- Retroactive Modeling and Type Constraining
- Where to Go From Here?
Back in the days when there was only Objective-C, encapsulation was limited to working with classes. However, in modern iOS and macOS programming using Swift, there are three choices: enums, structs and classes.
Combined with protocols, these types make it possible to create amazing things. While they share many common abilities, these types also have important differences.
The objective of this tutorial is to:
- Give you some experience using enums, structs and classes.
- Grant you some intuition about when to use them.
- Give you an understanding of how each works.
In terms of prerequisites, this tutorial assumes that you have at least the basics of Swift and some object-oriented programming experience. If you want to learn the basics of Swift checkout our Swift Apprentice Book
It’s All About Those Types
Three big selling points of Swift are its safety, speed and simplicity.
Safety implies that it’s difficult to accidentally write code that runs amok, corrupting memory and producing hard-to-find bugs. Swift makes your work safer because it tries to make it obvious when you have a bug by showing you problems at compile time, rather than hanging you out to dry at runtime.
The key to making this happen is the Swift type system:
Swift types are powerful, despite there being only six of them. That’s right – unlike many other languages that have literally dozens of built-in types, Swift only has six.
These consist of four named types: protocol
, enum
, struct
and class
. There are two compound types as well: tuple
and function
.
There are those other things that you might think of as basic types, such as Bool
, Int
, UInt
, Float
, etc. However, these are actually built up from the named types and delivered as part of the Swift Standard Library.
This tutorial focuses on the so-called named model types, which consist of enum
, struct
and class
.
Shapes With Scalable Vector Graphics (SVG)
As a working example, you’ll build a safe, speedy and simple SVG shape (scalable vector graphics) rendering framework.
SVG is an XML-based vector image format for 2D graphics. This specification has been an open standard developed by the W3C since 1999.
Getting Started
Create a new playground in Xcode to follow along by choosing File ▸ New ▸ Playground… from the menu. Next, choose the platform as macOS and choose the Blank template. Next, name it Shapes and choose a location to save it, then click Create to save the playground. Clear the file completely, then enter the following:
import Foundation
Your goal will be to render something like this:
<!DOCTYPE html>
<html>
<body>
<svg width='250' height='250'>
<rect x='110.0' y='10.0' width='100.0' height='130.0' stroke='teal'
fill='aqua' stroke-width='5' />
<circle cx='80.0' cy='160.0' r='60.0' stroke='red' fill='yellow'
stroke-width='5' />
</svg>
</body>
</html>
Using a WebKit view, it looks like this:
You’ll need a representation for colors. SVG uses the CSS3 color type that can be specified as a name, RGB or HSL. For more details, you can read the full specification.
To use a color in SVG, you specify it as an attribute of part of your drawing — for example, fill = 'gray'
. An easy approach to this in Swift is to use a String
— as in, let fill = "gray"
.
While using String
is easy and does the job, there are some major downsides:
- It’s error prone. Any strings that are not part of the color spectrum will compile fine but not show up correctly at runtime. For example, “grey” spelled with an “e” doesn’t work.
- Autocomplete won’t help you find valid color names.
- When you pass around a color as a parameter, it might not always be obvious that the string is a color.
Using Enums
Using a custom type solves these problems. If you’re coming from Cocoa Touch, you might think to implement an encapsulated class like UIColor
. While using a class design could work, Swift gives you more choices for how to define your model.
Without typing anything in just yet, first have a think how you might implement the colors as an enum.
You might think to implement it, like so:
enum ColorName {
case black
case silver
case gray
case white
case maroon
case red
// etc.
}
The above works very similarly to a set of C-style enums. However, unlike C-style enums, Swift gives you the option to specify a type to represent each case.
Enumerations that explicitly specify a backing store
type are referred to as RawRepresentable
, because they automatically conform to RawRepresentable
.
You can specify the type of ColorName
as String
, and you assign a value to each case, like so:
enum ColorName: String {
case black = "black"
case silver = "silver"
case gray = "gray"
case white = "white"
case maroon = "maroon"
case red = "red"
// etc.
}
However, Swift does something special for enums with a String
representation. If you don’t specify what the case is equal to, the compiler automatically makes the string the same as the name of the case. That means that you only need to write the case name:
enum ColorName: String {
case black
case silver
case gray
case white
case maroon
case red
// etc.
}
You can further reduce your typing by separating the cases with commas using the keyword case
just once.
Add the following code to the end of your playground:
enum ColorName: String {
case black, silver, gray, white, maroon, red, purple, fuchsia, green,
lime, olive, yellow, navy, blue, teal, aqua
}
Now, you have a first-class custom type and all the goodness that comes with that.
let fill = ColorName.grey // ERROR: Misspelled color names won't compile. Good!
let fill = ColorName.gray // Correct names autocomplete and compile. Yay!
CaseIterable
Enums in Swift are great for holding a list of items such as our example list of colors. To make enums even more powerful, Swift 4.2 added a new protocol named CaseIterable
that provides a collection of all the values of the conformer.
At compile time, Swift will automatically create an allCases
property that is an array of all your enum cases, in the order you defined them.
Using CaseIterable
is very simple. All you have to do is declare the conformance in the definition of ColorName
as shown below:
enum ColorName: String, CaseIterable {
case black, silver, gray, white, maroon, red, purple, fuchsia, green,
lime, olive, yellow, navy, blue, teal, aqua
}
You can then use the allCases
property whose type is [ColorName]
. Add the following to the end of your playground:
for color in ColorName.allCases {
print("I love the color \(color).")
}
In the console, you’ll see 16 lines printed — one for every color in ColorName
.