[英]Swift: How to access variable element of an enum?
For hours I've been struggeling with getting an variable element of an enum. 几个小时以来,我一直在努力获取枚举的可变元素。
The " Swifticons " - pod provides me with the following enum: “ Swifticons ” -pod为我提供了以下枚举:
public enum WeatherType: Int {
static var count: Int {
return weatherIcons.count
}
public var text: String? {
return weatherIcons[rawValue]
}
case alien, barometer, celsius, owm300, owm301, owm302, and200moreOfTheseNames
}
private let weatherIcons = ["\u{f075}", "\u{f079}", and202moreOfTheseFontCharacters]
From an external API ( openWeatherMap.org ) I just get an weather code (let's say "300") - and I want to access Icon "owm300". 从一个外部API( openWeatherMap.org ),我仅获得一个天气代码(比如说“ 300”),并且我想访问图标“ owm300”。
But how do I access this element of the enum without knowing the rawValue (which would be - say - 198)? 但是,如何在不知道rawValue的情况下访问枚举的此元素(即-198)?
One of the easiest way I can think of is create some kind of mapping dictionary, where you would keep track of weather response code and WeatherType that it maps to like so, 我想到的最简单的方法之一就是创建某种映射字典,在其中您可以跟踪天气响应代码和它映射到的WeatherType,
let weatherCodeMapping: [Int: WeatherType] = [300: .owm300,
301: .owm301,
302: .owm302]
With this in place, you dont need to know any specific rawValue, you can simply get code by, 有了这个,您就不需要知道任何特定的rawValue,只需通过以下方式获取代码,
let weatherType = weatherCodeMapping[weatherCode]
And then create some other mapping for your image based on the weatherType. 然后根据weatherType为图像创建其他映射。
let weatherIcon = weatherIconMapping[weatherType]
or create a single mapping directly from weather code to icon. 或直接从天气代码到图标创建单个映射。
Here's the plan: 这是计划:
WeatherType
is backed by Int
). WeatherType
由Int
支持)。 String
to WeatherType
. String
映射到WeatherType
。 WeatherType?
WeatherType?
because we can encounter an unknown value. Here's the code: 这是代码:
extension WeatherType {
// just some little convenience
private typealias W = WeatherType
// 1. define the sequence of all cases
private static func allCases() -> AnySequence<W> {
return AnySequence { () -> AnyIterator<W> in
var raw = 0
return AnyIterator {
// Iterates while raw value can be converted to an enum case
if let next = W(rawValue: raw) {
raw += 1
return next
}
return nil
}
}
}
// 2. Static properties are lazy so we'll use them to store the dictionary with String to WeatherType mapping
private static let typeMap = W.allCases().reduce([String: W]()) { acc, next in
var acc = acc
acc[String(describing: next)] = next
return acc
}
// 3. Declare the mapping function
static func from(string: String) -> WeatherType? {
return W.typeMap[string]
}
}
Here's a little test: 这是一个小测试:
let str = "301"
let type = WeatherType.from(string: "owm\(str)")
print(type == .owm301)
Swift doesn't currently have enumerable sequences of enum cases. Swift当前没有枚举实例的可枚举序列。 One option that you have is to copy the list of icon names , then search for your icon's name, and use that index as the enum's rawValue:
您拥有的一种选择是复制图标名称列表 ,然后搜索图标的名称,并将该索引用作枚举的rawValue:
let weatherIcons = [...]
let iconName = "owm300"
let possibleIconIndex = weatherIcons.index {
$0.caseInsensitiveCompare(iconName) == .orderedSame
}
if let iconIndex = possibleIconIndex {
let weatherIcon = WeatherIcon(rawValue: iconIndex)!
// ...
} else {
// graceful fallback for when the weather icon is missing
}
Of course, you need to figure out your own mapping between the data you get from the service and enum names, but that could be as simple as "owm\\(weatherCode)"
. 当然,您需要弄清楚从服务获取的数据和枚举名称之间的映射关系,但这可能很简单,例如
"owm\\(weatherCode)"
。
When Swift 4.2 lands, you will be able to make your enums conform to a new protocol called CaseIterable
. 当Swift 4.2登陆时,您将能够使您的枚举符合一个名为
CaseIterable
的新协议。 Enums that conform to it get a synthesized implementation of an allCases
static variable. 符合它的枚举将获得
allCases
静态变量的综合实现。 You will then be able to use that enumeration to build a string-to-enum dictionary automatically: 然后,您将可以使用该枚举自动构建字符串到枚举的字典:
let nameToEnum = WeatherIcon.allCases.map { (String($0), $0) }
let mapping = Dictionary(uniqueKeysWithValues: nameToEnum)
That will however require WeatherIcon
to be declared with the CaseEnumerable
conformance, as adding it with an extension
has no effect. 但是,这将要求
WeatherIcon
声明为CaseEnumerable
一致性,因为添加extension
不会起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.