Programming in Swift: Functions & Types

Jan 4 2022 · Swift 5.5, iOS 15, Xcode 13

Part 3: Enumerations

26. Associated Values

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 25. Challenge: Switch Statements Next episode: 27. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 26. Associated Values

Update Notes: This course was originally recorded in 2019. It has been reviewed and all content and materials updated as of October 2021.

Transcript: 26. Associated Values

Now that you’ve got a handle on switch statements, there’s one more important thing to cover about enumerations.

There’s another way to associate values with your enumeration instances. They are literally called “associated values”. These work differently than raw values, in that they let you associate a custom value (or values) with each enumeration case.

The values for each case have their own data type, and each case can have zero or more associated values. You can also define associated values with label names like you would for named function parameters.

One more important thing to note: An enumeration can have raw values or associated values, but not both.

Associated values can take Swift enumerations to the next level in expressive power. So, let’s try them out!

Let’s revisit something we were looking at when we learned about switch statements: TwoDimensionalPoints. We can create an enumeration for that!

enum TwoDimensionalPoint {

}

One case is the origin.

case origin

Other cases could use some associated values. Like when the point is on the X or Y axis. You can add how far along the axis, using a Double.

case onXAxis(Double)
case onYAxis(Double)

And sometimes, you’ll need a pair of Doubles! Such as when there’s no zero coordinate.

case noZeroCoordinate(x: Double, y: Double)

For that case, I gave a label to each value. To try this enumeration out, define some coordinates, using a tuple of doubles, and declare a TwoDimensionalPoint constant.

let coordinates = (1.0, 3.0)
let twoDimensionalPoint: TwoDimensionalPoint

Switch on coordinates, and by default, make an assignment using noZeroCoordinate, like this:

switch coordinates {
default: 
  twoDimensionalPoint = .noZeroCoordinate(x: coordinates.0, y: coordinates.1)
}

To create that enumeration instance, we had to pass in something for each associated value.

The origin case is extra-simple, because it doesn’t have an associated value

case (0, 0): 
  twoDimensionalPoint = .origin

Try change coordinates to (0.0, 0.0) to see that working.

let coordinates = (0.0, 0.0)

And the last two cases can look very similar to one another.

case (_, 0):
  twoDimensionalPoint = .onXAxis(coordinates.0)
case (0, _):
  twoDimensionalPoint = .onYAxis(coordinates.1)

Now try changing coordinates to something with 0 as only one of the values.

let coordinates = (0.0, 7.0)

And run the playground to see the results show up for those in the sidebar. Before we head out for this part of the course, let’s take it in reverse, getting the associated value back out of the enumeration instance.

This time, we’ll wrap things up in a function. It should take in a TwoDimensionalPoint and return a tuple of Doubles, labeled x and y.

func getValues(for point: TwoDimensionalPoint) -> (x: Double, y: Double) {

}

Inside of that function, switch on the point parameter!

switch point {

}

In the origin case, there’s no associated value, but we know what it corresponds to: two zeros.

case .origin:
  return (0, 0)

When you’ve got an associated value, you can bind with the let keyword either before the enumeration case name and dot…

case let .onXAxis(x):
  return (x, 0)

…or inside the parentheses.

case .onYAxis(let y):
  return (0, y)

For multiple associated values, it’s better to use the let before the dot. Otherwise, you’d need to write let multiple times, inside the parentheses, once for each bound value.

case let .noZeroCoordinate(x, y):
  return (x, y)

Try all of those cases out by passing different values into the function!

getValues(for: .origin)
getValues(for: .onXAxis(66.6))
getValues(for: .onYAxis(-3.5))
getValues(for: TwoDimensionalPoint.noZeroCoordinate(x: 5, y: 7))

And run the playground one more time to see the results!