Search code examples
swiftenumsvariable-declarationternary

How to declare a variable type depending on a ternary expression?


I have this enum :

enum WeatherMapDisplayType {
    case temperature
    case wind
}

Can I declare a variable like this ?

let markerView: mode == .temperature ? WeatherMapItemTemp : WeatherMapItemWind = UIView.fromNib()

Knowing that mode is of type WeatherMapDisplayType

How can I handle this scenario in an elegant way ?

EDIT:

I want to be able to do something like this :

let markerView: WeatherMapItem = UIView.fromNib()
markerView.frame = CGRect(x: 0, y: 0, width: 80, height: 30)
markerView.setupWeatherInformations(mode: self.currentDisplayMode, forecast: forecasts)
marker.iconView = markerView

Previously I only had WeatherMapItem type.

Then I have been asked to add an other weather map item, that is why I have the WeatherMapItemTemp and WeatherMapItemWind now (also corresponding to my enum display type).


func setupWeatherInformations(forecast: Forecast.HourlyForecast)

This is a method in my custom classes in order to configure the outlets.

But I don't have access to this method if I init my custom view from frame, because it's of UIView type.


Solution

  • Add a common protocol to these views:

    protocol WeatherMapItem where Self: UIView {
        func setupWeatherInformations()
    }
    
    class WeatherMapItemTemp: UIView, WeatherMapItem {
        func setupWeatherInformations() {
            // setup
        }
    }
    
    class WeatherMapItemWind: UIView, WeatherMapItem {
        func setupWeatherInformations() {
            // setup
        }
    }
    

    Add a computed variable to the enum:

    enum WeatherMapDisplayType {
        case temperature
        case wind
    
        var view: (UIView & WeatherMapItem)? {
            var nibName: String? = nil
            switch self {
            case .temperature:
                nibName = "WeatherMapItemTemp"
            case .wind:
                nibName = "WeatherMapItemWind"
            }
            if let nibName = nibName, let views = Bundle.main.loadNibNamed(nibName, owner: nil), views.count > 0 {
                return views[0] as? UIView & WeatherMapItem
            }
            return nil
        }
    }
    

    Now you can generate a view like so:

    // assuming mode is the variable of type WeatherMapDisplayType
    let view = mode.view
    view?.setupWeatherInformations()
    return view