2014-10-08 9 views
14

sto cercando di scegliere in modo casuale un valore enum, questo è il mio tentativo in corso:Swift: ha scelto un valore di enumerazione casuale

enum GeometryClassification { 

    case Circle 
    case Square 
    case Triangle 
    case GeometryClassificationMax 

} 

e la selezione casuale:

let shapeGeometry = (arc4random() % GeometryClassification.GeometryClassificationMax) as GeometryClassification 

questo però fallisce miseramente.

ricevo errori come:

'GeometryClassification' is not convertible to 'UInt32' 

tutte le idee su come risolvere questo?

risposta

22

io non sono pazzo per il tuo ultimo caso ci - sembra che si sta includendo .GeometryClassificationMax esclusivamente per consentire a caso selezione. Dovrai tenere conto di quel caso in più ovunque utilizzi un'istruzione switch e non ha valore semantico. Invece, un metodo statico su enum potrebbe determinare il valore massimo e restituire un caso casuale, e sarebbe molto più comprensibile e mantenibile.

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)! 
    } 
} 

E ora si può esaurire il enum in una switch dichiarazione:

switch GeometryClassification.randomGeometry() { 
case .Circle: 
    println("Circle") 
case .Square: 
    println("Square") 
case .Triangle: 
    println("Triangle") 
} 
+3

hai ragione - sono andato con questo approccio alla fine per renderlo più leggibile. grazie per lo sforzo –

+0

'++ maxValue' sarà deprecato in Swift 3. Come faresti a correggerlo nel tuo codice? – Cesare

+0

@Cesare: è possibile spostare l'incremento all'interno del ciclo 'while'. –

5

È necessario assegnare un tipo non elaborato all'enumerazione. Se si utilizza un tipo intero, i valori di casi di enumerazione sarà generato automaticamente a partire da 0:

enum GeometryClassification: UInt32 { 
    case Circle 
    case Square 
    case Triangle 
    case GeometryClassificationMax 
} 

"A differenza di C e Objective-C, i membri di enumerazione Swift non viene assegnato un valore di default di un intero al momento della creazione ". - come da pagina this. Specificando il tipo intero, consente di sapere come generare i valori nel solito modo.

Quindi è possibile generare il valore casuale in questo modo:

let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))! 

Questa è una orribilmente brutto chiamata, e tutte quelle 'fromRaw' e chiede 'toRaw' sono abbastanza poco elegante, quindi consiglio vivamente la generazione di un UInt32 casuale che è nella gamma che si desidera, poi la creazione di un GeometryClassification da quel valore:

GeometryClassification.fromRaw(someRandomUInt32) 
+0

Non è necessario assegnare i valori specifici in questo caso; verranno generati automaticamente a partire da "0". La parte che hai citato dai documenti è solo se l''enum' non ha un tipo raw basato su un intero. Più in basso nello stesso documento: "Quando gli interi vengono utilizzati per i valori non elaborati, vengono incrementati automaticamente se non viene specificato alcun valore per alcuni membri dell'enumerazione." –

+0

lo stesso errore rimane tristemente:/ –

+0

@ SebastianFlückiger è necessario creare 'GeometryClassification' dal valore raw restituito da' arc4random': 'let shapeGeometry = GeometryClassification (rawValue: (arc4random()% GeometryClassification.GeometryClassificationMax.rawValue))) ' –

7

Visto che siete all'interno della classe enum, avendo il metodo random() di riferimento il valore più alto in modo esplicito eliminerebbe dover contarli ogni volta:

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)! 
    } 
} 
+0

Questo non funziona a partire da Swift 1.2. Vuole un valore raw assegnato all'enum. A sua volta significa che funziona solo con le enumerazioni con un tipo raw Raw. – BadmintonCat

+0

Ho avuto un errore di battitura sul mio codice, restituivo il tipo sbagliato. – stevex

1

Ecco la mia Swift 1.2 introito:

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)! 
    } 
} 
Problemi correlati