2014-11-13 10 views
18

sto scrivendo il mio primo progetto in Swift (ho fatto ObjectiveC per anni) e per qualche motivo, non riesco a capire perché il mio enum e Switch non funzionano togetberSwitch: Enum Switch issue: Non membro di un

enum ContactViewMode : Int 
    { 
     case ViewModeFavourite = 0 
     case ViewModeRecent = 1 
     case ViewModeContacts = 2 
    } 

Proprietà

@IBInspectable var contactViewMode : Int! 

interruttore

switch contactViewMode { 
      case ContactViewMode.ViewModeFavourite: 
       contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
      case ContactViewMode.ViewModeRecent: 
       contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
      default: 
       contacts = DBManager.getAllContacts() as [ContactEntity] 
     } 

L'errore che ottengo è Il caso Enum 'ViewModeFavourite' non è un membro di tipo 'Int!'

Quindi l'ho modificato perché non è un Int! (Ho bisogno Int! Per Storyboard)

var contactMode:Int = contactViewMode 

     switch contactMode { 
      case .ViewModeFavourite: 
       contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
      case .ViewModeRecent: 
       contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
      default: 
       contacts = DBManager.getAllContacts() as [ContactEntity] 
     } 

tanto sono Enum caso del modello non può corrispondere i valori di tipo non-enum 'Int'

risposta

24

si deve dichiarare contactViewMode come ContactViewMode e non Int.

Se si vuole veramente che sia Int, allora è necessario cambiare i casi in switch, confrontando la variabile al rawValue proprietà dei casi enum:

switch contactViewMode { 
case ContactViewMode.ViewModeFavourite.rawValue: 
    contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
case ContactViewMode.ViewModeRecent.rawValue: 
    contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
default: 
    contacts = DBManager.getAllContacts() as [ContactEntity] 
} 

ma se non hai una buona motivo per questo, non lo consiglierei

3

enumerazioni sono tipi. Solo perché si rende chiaro che i singoli valori enum possono essere espressi su Int non rendono valido dichiarare contactViewMode uno Int!. I tipi semplicemente non corrispondono.

Quindi, o dichiarano contactViewMode come ContactViewMode, utilizzare il primo switch dichiarazione e cast per Int! quando è effettivamente necessario per lo storyboard, o utilizzare il secondo switch, ma non usano .ViewModeFacourite et al, ma il corrispondente valore di Int.

var contactMode:Int = contactViewMode 

    switch contactMode { 
     case ContactViewMode.ViewModeFavourite.rawValue: 
      contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
     case ContactViewMode..ViewModeRecent.rawValue: 
      contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
     default: 
      contacts = DBManager.getAllContacts() as [ContactEntity] 
    } 
2

Non è possibile abbinare direttamente Int con enum. Invece, devi convertire ContactViewMode in Int con .rawValue proprietà, o convertire Int in ContactViewMode con inizializzatore init(rawValue:).

L'ultimo esempio:

switch ContactViewMode(rawValue: contactViewMode) { 
case .Some(.ViewModeFavourite): 
    contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
case .Some(.ViewModeRecent): 
    contacts = DBManager.getFavouriteContacts() as [ContactEntity] 
default: 
    contacts = DBManager.getAllContacts() as [ContactEntity] 
} 

perchè ContactViewMode(rawValue:) restituisce Optional, abbiamo bisogno .Some().

+1

Che cosa fa esattamente il '.Some'? Hai un link ai documenti? – fabian789

+1

@ fabian789 Si chiama ["Modello di caso di enumerazione"] (https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/Patterns.html#//apple_ref/doc/uid/TP40014097-CH36 -XID_1012). Poiché ['Opzionale'] (https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-XID_1126) è solo un 'enum' (' .None' o '.Some (T)'), possiamo confrontarci con esso con quei pattern. – rintaro

5

Questo ha funzionato per me:

Ho un enum come questo:

enum Proximity{ 
    case Unknown 
    case Immediate 
    case Near 
    case Far 
} 

Poi un interruttore che assomiglia a questo:

switch b.proximity as Proximity { 
    case Proximity.Immediate: 
     if b.rssi == -30 && b.accuracy == 0.2345{ 
      closestBeacon = b 
     } 
    case Proximity.Near: 
     return 
    case Proximity.Far: 
     return 
    default: 
     return 
} 

Im loop attraverso una serie di "b "oggetti che hanno una proprietà di prossimità.

+0

Mi piace questa risposta. –

+0

Ancora non capisco, perché dobbiamo fare 'b.proximity as Proximity' .. il compilatore non dovrebbe sapere che' b.proximity' è di tipo 'Proximity'? –

14

Le altre risposte non sfruttano la forte digitazione di Swift. Si noti che tutti hanno un caso default nel loro switch. Swift può sapere al momento della compilazione, tuttavia, se hai coperto tutti i casi di un enum o meno, rendendo così il caso default non necessario.

Questa è una funzionalità utile della lingua. Immagina di aggiungere un ulteriore case al tuo enum in un secondo momento. Il compilatore si lamenterà e indicherà tutti gli switch che non stanno considerando quel particolare case.

Come possiamo sfruttare la forte digitazione di Swift, quindi?

Per prima cosa, risolviamo il nome dell'enumerazione. Come suppongo tu stia inserendo questo in una classe ContactView (e, a differenza di Objective-C, dovrebbe essere davvero all'interno di), puoi chiamare lo enum semplicemente Mode. Non c'è bisogno di menzionare anche ViewMode s. In questo modo ottieni un tipo più pulito e più idiomatico.

enum Mode: Int { 
    case Favourite 
    case Recent 
    case Contacts 
} 

Quello che dobbiamo fare è quello di eseguire la switch su un Mode, non su un Int. Il tuo Mode è RawRepresentable, e come tale si può fare:

guard let m = Mode(rawValue: contactViewMode) else { /* handle the situation */ } 
switch m { 
    case .Favourite: /* handle case */ 
    case .Recent: /* handle case */ 
    case .Contacts: /* handle case */ 
} 

Questo è tutto quello che c'è da, invece di accendere il rawValue, ottenere la giusta Mode prima e poi passare su di esso.

+0

Questa dovrebbe essere la risposta accettata. –

+0

Anche il valore di .rawValue è la scelta di molte persone, credo che questa risposta sia il modo più elegante di codificare. Immagina: ci sono cento elementi nel tipo enum, il modo .rawValue è davvero brutto. –