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?

16
demandé sur Sebastian Flückiger 2014-10-08 19:42:06

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")
}
22
répondu Nate Cook 2016-06-02 19:12:40

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)!
    }
}
7
répondu stevex 2015-05-14 10:37:24

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)
5
répondu Ideasthete 2014-10-08 16:22:45

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)!
    }
}
1
répondu BadmintonCat 2015-05-14 06:49:16

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]
    }
}
1
répondu Sandeep 2018-03-20 13:25:53