UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

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

Reply to this topic…

You need to create an account or log in to reply.

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.