Barrrdi
Barrrdi

Reputation: 1161

Using Enums’ associated values to link cases from first Enum to 2nd, then call an associated function value from the CaseIterable second

I’m building a weather app that will provide access to multiple weather providers from which I get slightly-to-very different data sets returned. I want to make the system that handles the setting up of the data to be as generic as possible to accelerate the addition of new providers.

Firstly, I have an enum RValueUnits that consists of all possible units that values can be returned in:

enum RValueTypes { /// returned value
    case cm
    case celsius
    case decimal
    case mm
    case percentage
    case inch
    /// etc
}

Some providers, for example, may return precipitation amount in .mm, others in .cm.

What I want is for each provider to have an enum of their own listing all the properties that they return including the return type. For example:

enum DarkSkyProps: CaseIterable {
    static var allCases: [DarkSkyProps] {
        return [
            .apparentTemperature(unit: .celsius, setter: setApparentTemperature)
        ]}
    
    case apparentTemperature(unit: RValueType, setter: () throws -> Void)
}

The setter function associated with each case handles the property’s data set up. For example, it would compare the return value type from the provider with the user’s preference, and if it’s different, it will change it before setting it as the value of the associated property, for example apparentTemperature in the above case.

static func setApparentTemperature() throws {
    /// processing logic goes here
}

I have one issue and one question:

Firstly, I wanted DarkSkyProps to be CaseIterable so the setup is automatic. However, I have no idea how to call the iterated case’s associated setter function:

for property in DarkSkyProps.allCases {
  /// want to call property.setter()
}

Secondly, ideally I also want there to be enum ForecastSource such as:

enum ForecastSource {
    case DarkSky
    case Foreca
}

And for each to be associated with a Props enum (i.e. ForecastSource.DarkSky is linked to DarkSkyProps), like:

case DarkSky(props: DarkSkyProps.AllCases)

So that I then need to only write something like, for example:

var source: ForecastSource = .DarkSky
for property in source.props {
    /// want to call property.setter()
}

Is there a way?

Finally, considering what I’m aiming for, is there an actually entirely different approach that is more suitable?

Many thanks!

Upvotes: 0

Views: 94

Answers (0)

Related Questions