DEV Community

Jaume Viñas Navas
Jaume Viñas Navas

Posted on

3

Swift Enumerations (Part 2)

In this new chapter we will cover more advanced features about Swift enumerations, remember to read the first chapter if you missed it or you want to refresh the basic concepts of Swift enums.

Associated Values

Enumeration cases have their own value and type, and sometimes it is useful to store additional data of other types alongside an enum case. Associated values are a fantastic way to achieve that by attaching custom information along with the case value, allowing this information to be different each time you use that enum case in your code.

Here’s an example of an enumeration that defines a set of actions that users can execute in order to modify a layer. A layer can be resized, rotated and filled with a color. The enum case resize has two associated values that define the new width and height values of the layer, the enum case rotate has one associated value which indicates the rotation degrees, and the enum case fill has one associated value that indicates the color of the layer.

enum LayerActions {
case scale(width: Double, height: Double)
case rotate(degrees: Double)
case fill(hex: String)
}
let scale = LayerActions.scale(width: 120, height: 60)
let fill = LayerActions.fill(hex: "#FFFFFF")
view raw enums_av.swift hosted with ❤ by GitHub

The associated values can be accessed using a switch statement, and they can be extracted as constants (with the let prefix) or as variables (with the var prefix).

let fill = LayerActions.fill(color: "#FFFFFF")
switch fill {
case .scale(let width, let height):
print("Layer size: \(width)x\(height)")
case .rotate(let degrees):
print("Layer rotation: \(degrees)")
case .fill(let color):
print("Layer color: \(color)")
}

Methods

Enumerations in Swift are first-class types in their own right. They adopt many features traditionally supported only by classes, for example, instance methods to provide functionality related to the values the enumeration represents.

Methods on enumerations exist for every enum case. If you want to provide specific code for every enum case, you need a switch statement to determine each case.

enum Polygon {
case triangle, quadrilateral, pentagon, hexagon
func description() -> String {
switch self {
case .triangle:
return "A triangle is a polygon with three egdes"
case .quadrilateral:
return "A quadrilateral is a polygon with four egdes"
case .pentagon:
return "A pentagon is a polygon with five egdes"
case .hexagon:
return "An hexagon is a polygon with six egdes"
}
}
}

Mutating Methods

By default, the properties of an enumeration cannot be modified from within its instance methods. However, if you need to modify your enumeration you can use mutating methods. Mutating methods for enumerations can set the implicit self parameter to be a different case from the same enumeration.

Here’s an example that defines an enumeration for a temperature alarm with two states, enabled and disabled. The enumeration changes its state when the temperature reaches an specific threshold.

enum Alarm {
case enabled, disabled
mutating func newReading(temperature: Double) {
if (temperature > 300) {
self = .enabled
} else {
self = .disabled
}
}
func description() -> String {
switch self {
case .enabled:
return "Alarm is enabled"
case .disabled:
return "Alarm is disabled"
}
}
}
var ovenAlarm = Alarm.disabled
ovenAlarm.newReading(temperature: 340)
ovenAlarm.description() // "Alarm is enabled"

Properties

Event though enumerations can’t have stored properties, they can have computed properties to provide additional information about the enumeration’s current value.

The example below modifies the Polygon enumeration in order to add a new property edges . This new property returns the number of edges of the enum case. The method description() has also been updated in order to use the new property.

enum Polygon {
case triangle, quadrilateral, pentagon, hexagon
var edges: Int {
switch self {
case .triangle:
return 3
case .quadrilateral:
return 4
case .pentagon:
return 5
case .hexagon:
return 6
}
}
func description() -> String {
switch self {
case .triangle:
return "A triangle is a polygon with \(self.edges) egdes"
case .quadrilateral:
return "A quadrilateral is a polygon with \(self.edges) egdes"
case .pentagon:
return "A pentagon is a polygon with \(self.edges) egdes"
case .hexagon:
return "An hexagon is a polygon with \(self.edges) egdes"
}
}
}

If you find this post helpful, please recommend it for others to read. In the next chapter we will cover more advanced enumeration usages such as protocols, extensions, generics and custom initializers.

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more