Seb*_*ger 22 random enums swift
我试图随机选择一个枚举值,这是我目前的尝试:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
Run Code Online (Sandbox Code Playgroud)
和随机选择:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
Run Code Online (Sandbox Code Playgroud)
然而,这无可救药地失败了.
我得到的错误如下:
'GeometryClassification' is not convertible to 'UInt32'
Run Code Online (Sandbox Code Playgroud)
关于如何解决这个问题的任何想法?
Nat*_*ook 30
我对你在那里的最后一个案子并不感到疯狂 - 似乎你.GeometryClassificationMax
只是为了启用随机选择.在使用switch
语句的任何地方,您都需要考虑该额外情况,并且它没有语义值.相反,静态方法enum
可以确定最大值并返回随机情况,并且更易于理解和维护.
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
private static let _count: GeometryClassification.RawValue = {
// find the maximum enum value
var maxValue: UInt32 = 0
while let _ = GeometryClassification(rawValue: maxValue) {
maxValue += 1
}
return maxValue
}()
static func randomGeometry() -> GeometryClassification {
// pick and return a new value
let rand = arc4random_uniform(_count)
return GeometryClassification(rawValue: rand)!
}
}
Run Code Online (Sandbox Code Playgroud)
你现在可以enum
在switch
声明中用尽:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
Run Code Online (Sandbox Code Playgroud)
Pha*_*nik 19
在Swift中,实际上有一个用于枚举的协议CaseIterable
,如果将其添加到枚举中,则可以将所有用例作为一个集合引用.allCases
为:
enum GeometryClassification: CaseIterable {
case Circle
case Square
case Triangle
}
Run Code Online (Sandbox Code Playgroud)
然后您可以.allCases
然后.randomElement()
随机获得一个
let randomGeometry = GeometryClassification.allCases.randomElement()!
Run Code Online (Sandbox Code Playgroud)
需要进行强制展开,因为有可能枚举没有大小写,因此randomElement()
将返回nil
。
因为你在enum类中,所以显式地使用random()方法引用最高值将不必每次都计算它们:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
static func random() -> GeometryClassification {
// Update as new enumerations are added
let maxValue = Triangle.rawValue
let rand = arc4random_uniform(maxValue+1)
return GeometryClassification(rawValue: rand)!
}
}
Run Code Online (Sandbox Code Playgroud)
对于 Swift 5,有“ RandomNumberGenerator ”:
enum Weekday: CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Weekday {
return Weekday.allCases.randomElement(using: &generator)!
}
static func random() -> Weekday {
var g = SystemRandomNumberGenerator()
return Weekday.random(using: &g)
}
}
Run Code Online (Sandbox Code Playgroud)
您需要为枚举分配原始类型.如果使用整数类型,则枚举大小写值将从0开始自动生成:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
Run Code Online (Sandbox Code Playgroud)
"与C和Objective-C不同,Swift枚举成员在创建时不会被赋予默认的整数值." - 按此页面.指定整数类型可让它知道以通常的方式生成值.
然后你可以像这样生成随机值:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
Run Code Online (Sandbox Code Playgroud)
这是一个非常丑陋的调用,所有那些'fromRaw'和'toRaw'调用相当不优雅,所以我真的建议生成一个你想要的范围内的随机UInt32,然后从该值创建一个GeometryClassification:
GeometryClassification.fromRaw(someRandomUInt32)
Run Code Online (Sandbox Code Playgroud)