13.3 Associated Values
As previously mentioned, you can also store custom information with your cases. This case-specific data is called an associated value.
The associated data can be of any type, and the type and name of any piece of associated data can vary from case to case. In other languages, features like this are known as discriminated unions, tagged unions, or variants.
For example, suppose an inventory tracking system needs to track products by two different types of barcode. Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0 to 9. Each barcode has a “number system” digit, followed by five “manufacturer code” digits and five “product code” digits. These are followed by a “check” digit to verify that the code has been scanned correctly:
Other products are labeled with 2D barcodes in QR code format, which can use any ISO 8859-1 character and can encode a string up to 2,953 characters long:
It would be convenient for an inventory tracking system to be able to store UPC barcodes as a tuple of four integers, and QR code barcodes as a string of any length.
In Swift, an enumeration to define product barcodes of either type might look like this:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
We could then define a Barcode of either type:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
//Reassigning it to be a QR Code
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
You can then extract any individual piece of data as part of a switch statement's case body using the let
(for constants) or var
(for variables) keywords:
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."
If all the associated data will be extracted as either as constants or as variables, you can place a single var or let before the annotation for the case name (see lines 2 and 4):
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."