给出一个Swift枚举:
enum PerformerPosition: Int {
case String_Violin1
case String_Violin2
case String_Viola
case String_Cello
case String_CB
case Wind_Oboe
case Wind_Clarinet
case Wind_Flute
...
}
Run Code Online (Sandbox Code Playgroud)
(对于项目的需要,我无法使用嵌套枚举.)我想只选择带String_前缀的枚举值.
到目前为止,我所知道的唯一方法是从所有可用的案例中执行随机枚举值,如下所示:
private static let _count: PerformerPosition.RawValue = {
// find the maximum enum value
var maxValue: Int = 0
while let _ = PerformerPosition(rawValue: maxValue) {
maxValue += 1
}
return maxValue
}()
static func randomPerformer() -> PerformerPosition {
// pick and return a new value
let rand = arc4random_uniform(UInt32(count))
return PlayerPosition(rawValue: Int(rand))!
}
Run Code Online (Sandbox Code Playgroud)
我怎么能这样做,所以我能够选择一个基于String_前缀的随机值,而不必求助于硬编码一个较高的值(例如,String_可能会添加新的前缀位置)?谢谢
因此,即使添加了新职位,您也不想更改任何代码。正确的?
为此,您需要动态获取所有枚举案例,而不是对它们进行硬编码。根据这个答案,您可以使用此方法来获取所有案例:
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
掌握了这个cases方法后,你可以通过以下方式轻松获得你想要的东西:
let startingWithString = Array(PerformerPosition.cases().filter { "\($0)".hasPrefix("String_") })
let rand = arc4random_uniform(UInt32(startingWithString.count))
let randomPosition = startingWithString[Int(rand)]
Run Code Online (Sandbox Code Playgroud)