LAST CHANCE: Save 50% on all my Swift books and bundles! >>

Enum with Dictionary Values

Forums > SwiftUI

Why would you want to use Enum with dictionary values, because you get the benefit of the features of using an enum (closed, consistent and complete list) with the possibility of having associated values for any additional functionality (icons, labels, text, accessibility labels, etc.).

There maybe a better or different way to get the same effect, so consider

enum VolumeSetting: String, CaseIterable, Identifiable {
    case loud = "Loud"
    case normal = "Normal"
    case soft = "Soft"

    var id: String { self.rawValue }
}

func volumeValue(for volume: VolumeSetting) -> Float {
    // do not want to increase dictionary size either deliberately or by accident
    guard VolumeSetting.allCases.contains(volume) else { return 0.5 }

    let volumeValue: [VolumeSetting: Float] = [
        .loud: 0.75,
        .normal: 0.5,
        .soft: 0.25
    ]

    return volumeValue[volume]!
}

func volumeIcon (for volume: VolumeSetting) -> String {
    // do not want to increase dictionary size either deliberately or by accident
    guard VolumeSetting.allCases.contains(volume) else { return "speaker.wave.2" }

    let volumeIcon: [VolumeSetting: String] = [
        .loud: "speaker.wave.3",
        .normal: "speaker.wave.2",
        .soft: "speaker.wave.1"
    ]

    return volumeIcon[volume]!
}

Assuming that audioPlayer has already been created as an AVAudioPlayer type instance, you can write

audioPlayer?.setVolume(volumeValue(for: volumeSetting), fadeDuration: 3)

and 'volumeSetting' is defined as a VolumeSetting enum.

playAlarmSound(volumeSetting)

and

Button("\(Image(systemName: volumeIcon(for: volumeSetting)))") {
       // more code here
}
.accessibilityElement()
.accessibilityLabel("Volume")
.accessibilityHint("Volume is \(volumeSetting.rawValue.description)")

2      

Rather than have freestanding functions that provide that information and involve creating a Dictionary, you can just add computed properties to your enum. And you won't need a guard to make sure your function has been passed a valid VolumeSetting value, because the compiler will ensure that you can only have legit values.

enum VolumeSetting: String, CaseIterable, Identifiable {
    case loud = "Loud"
    case normal = "Normal"
    case soft = "Soft"

    var id: String { self.rawValue }

    var value: Float { 
    //although I might come up with a better name than this
        switch self {
            case .loud: return 0.75
            case .normal: return 0.5
            case .soft: return 0.25
        }
    }

    var icon: String {
        switch self {
            case .loud: return "speaker.wave.3"
            case .normal: return "speaker.wave.2"
            case .soft: return "speaker.wave.1"
        }
    }
}

And usage like so:

audioPlayer?.setVolume(volumeSetting.value, fadeDuration: 3)

and

playAlarmSound(volumeSetting)

and

Button("\(Image(systemName: volumeSetting.icon))") {
       // more code here
}
.accessibilityElement()
.accessibilityLabel("Volume")
.accessibilityHint("Volume is \(volumeSetting.rawValue)")
//don't need to use description here since the RawValue of your enum is a String

This is one of the great things about Swift enums, that they can have properties and methods and such. This way, everything is encapsulated right there in the enum itself.

4      

Hacking with Swift is sponsored by Essential Developer.

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until July 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.