我正在尝试随机选择一个枚举值,这是我目前的尝试:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
和随机选择:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
然而,这却失败了。
我得到的错误如下:
'GeometryClassification' is not convertible to 'UInt32'
关于如何解决这个问题的任何想法?
答案 0 :(得分:29)
自从撰写提供更好解决方案的答案后,Swift获得了新功能 - 请参阅this answer。
我对你的最后一个案例并不感到疯狂 - 似乎你只是将.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)!
}
}
您现在可以在enum
声明中耗尽switch
:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
答案 1 :(得分:8)
因为你在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)!
}
}
答案 2 :(得分:8)
在Swift中,实际上有一个名为CaseIterable
的枚举协议,如果将其添加到枚举中,则可以使用.allCases
将所有案例作为集合引用,如下所示:>
enum GeometryClassification: CaseIterable {
case Circle
case Square
case Triangle
}
然后您可以依次.allCases
和.randomElement()
来获得一个随机的
let randomGeometry = GeometryClassification.allCases.randomElement()!
需要强制展开,因为有可能枚举没有大小写,因此randomElement()
将返回nil
。
答案 3 :(得分:6)
对于Swift 5,有“ RandomNumberGenerator”:
<div class="header_library">
<div class="row">
<p>Выберите плейлист или несколько и нажмите кнопку</p>
<div style="margin: 10px;">
<input id="btn_transfer_checkbox" type="button" value="Перенести">
</div>
</div>
<div class="row">
<input id="btn_checked_all" type="button" value="Выбрать все">
</div>
</div>
<div>
Some elements
</div>
答案 4 :(得分:5)
您需要为枚举分配原始类型。如果使用整数类型,则枚举大小写值将从0开始自动生成:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
&#34;与C和Objective-C不同,Swift枚举成员在创建时不会被赋予默认的整数值。&#34; - 根据this页面。指定整数类型可以让它知道以通常的方式生成值。
然后你可以像这样生成随机值:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
这是一个非常丑陋的电话,而且所有那些来自“Raw&#39;并且&#39; toRaw&#39;调用是相当不优雅的,所以我真的建议先生成一个你想要的范围内的随机UInt32,然后从该值创建一个GeometryClassification:
GeometryClassification.fromRaw(someRandomUInt32)
答案 5 :(得分:1)
这是我的Swift 1.2拍摄:
enum GeometryClassification : Int {
case Circle = 0
case Square = 1
case Triangle = 2
static func random() -> GeometryClassification {
let min = MutationType.Circle.rawValue
let max = MutationType.Triangle.rawValue
let rand = Int.random(min: min, max: max) // Uses ExSwift!
return self(rawValue: rand)!
}
}
答案 6 :(得分:1)
您可以将所有值放入数组并生成随机,
extension GeometryClassification {
static func random() -> GeometryClassification {
let all: [GeometryClassification] = [.Circle,
.Square,
.Triangle,
.GeometryClassificationMax]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}
答案 7 :(得分:0)
我使用 Andy's 答案编写了一个全局扩展。享受:)
extension CaseIterable {
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Self.AllCases.Element {
return Self.allCases.randomElement(using: &generator)!
}
static func random() -> Self.AllCases.Element {
var g = SystemRandomNumberGenerator()
return Self.random(using: &g)
}
}
只需扩展您的枚举以符合 CaseIterable 协议并使用类似:
let state = YourEnum.random()
答案 8 :(得分:0)
最简单的方法是创建一个全局扩展:
extension CaseIterable {
static func randomElement() -> AllCases.Element {
guard Self.allCases.count > 0 else {
fatalError("There must be at least one case in the enum")
}
return Self.allCases.randomElement()!
}
}
这样任何符合 CaseIterable
的枚举都会自动具有该功能