Swift: choisir une valeur d'énumération aléatoire
j'essaie de choisir au hasard une valeur enum, c'est ma tentative actuelle:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
et la sélection aléatoire:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
ceci cependant échoue lamentablement.
j'ai des erreurs comme:
'GeometryClassification' is not convertible to 'UInt32'
aucune idée sur comment résoudre ce problème?
5 réponses
Je ne suis pas fou de votre dernière affaire là-bas -- il semble que vous incluez .GeometryClassificationMax
uniquement pour permettre la sélection aléatoire. Vous aurez besoin de compte pour ce cas partout où vous utilisez un switch
déclaration, et il n'a pas de valeur sémantique. Au lieu de cela, une méthode statique sur le enum
pourrait déterminer la valeur maximale et retourner un cas aléatoire, et serait beaucoup plus compréhensible et maintenable.
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)!
}
}
Et vous pouvez maintenant l'évacuation de l' enum
dans un switch
déclaration:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
puisque vous êtes dans la classe enum, avoir la référence de la méthode random() la plus haute valeur explicitement éliminerait d'avoir à les Compter à chaque fois:
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)!
}
}
vous devez assigner un type brut à votre enum. Si vous utilisez un type entier, alors les valeurs de cas d'énumération seront générées automatiquement à partir de 0:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
"contrairement à C et Objective-C, Les membres de l'énumération Swift ne se voient pas attribuer une valeur entière par défaut lorsqu'ils sont créés."- comme par page. Spécifier le type entier lui permet de générer les valeurs de la manière habituelle.
alors vous pouvez générer la valeur aléatoire comme ceci:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
c'est un appel horriblement laid, et tous ces appels "fromRaw" et "toRaw" sont assez inélégants, donc je recommande vraiment de générer un UInt32 aléatoire qui est dans la gamme que vous voulez d'abord, puis de créer une classification Géométrique À partir de cette valeur:
GeometryClassification.fromRaw(someRandomUInt32)
Voici mon 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)!
}
}
Vous pouvez mettre toutes les valeurs dans le tableau et générer au hasard,
extension GeometryClassification {
static func random() -> GeometryClassification {
let all: [GeometryClassification] = [.Circle,
.Square,
.Triangle,
.GeometryClassificationMax]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}