2015-08-30 14 views
7

Vorrei sostituire le mie costanti di stringa globali con un enumerato annidato per le chiavi che sto utilizzando per accedere alle colonne in un database.Valore stringa di accesso in enum senza utilizzare rawValue

La struttura è la seguente:

enum DatabaseKeys { 

    enum User: String { 
     case Table = "User" 
     case Username = "username" 
     ... 
    } 

    ... 

} 

Ogni tabella nel database è un enum interna, con il nome della tabella di essere il titolo del enum. Il primo caso in ogni enumerazione sarà il nome della tabella, e i seguenti casi sono le colonne nella sua tabella.

Per utilizzare questo, è abbastanza semplice:

myUser[DatabaseKeys.User.Username.rawValue] = "Johnny" 

Ma io userà queste enumerazioni un sacco. Dovendo aggiungere .rawValue ad ogni istanza sarà un problema, e non è leggibile come mi piacerebbe che fosse. Come posso accedere al valore String senza dover utilizzare rawValue? Sarebbe bello se posso fare questo:

myUser[DatabaseKeys.User.Username] = "Johnny" 

Si noti che sto usando Swift 2. Se c'è un modo migliore per ottenere questo risultato mi piacerebbe sentirla!

+0

Che tipo di oggetto è '' 'myUser'''? Un dizionario o il tuo oggetto con un pedice? –

+0

@AndyIbanez Potrebbe essere un dizionario semplice, o un PFUser nel mio caso perché sto usando Parse – Joey

risposta

14

Mentre non ho trovato un modo per farlo utilizzando la sintassi desiderato con enumerazioni, questo è possibile utilizzando le strutture.

struct DatabaseKeys { 

    struct User { 
     static let identifier = "User" 
     static let Username = "username" 
    } 

} 

Per utilizzare:

myUser[DatabaseKeys.User.Username] = "Johnny" 

Apple utilizza le strutture come questo per storyboard e tipo riga identificatori nei modelli WatchKit.

+0

Buono a sapersi che ~ thx amico – Jerome

6

È possibile utilizzare il protocollo CustomStringConvertible per questo.

Da documentazione,

String (esempio) funziona per un'istanza di qualsiasi tipo, tornando sua descrizione se l'istanza sembra essere CustomStringConvertible. L'utilizzo di CustomStringConvertible come un vincolo generico o l'accesso diretto a una descrizione del tipo conforme a , è pertanto sconsigliato.

Quindi, se si è conformi a questo protocollo e si restituisce rawValue tramite il metodo di descrizione, sarà possibile utilizzare String (Table.User) per ottenere il valore.

enum User: String, CustomStringConvertible { 

    case Table = "User" 
    case Username = "username" 

    var description: String { 
     return self.rawValue 
    } 
} 

var myUser = [String: String]() 
myUser[String(DatabaseKeys.User.Username)] = "Johnny" 

print(myUser) // ["username": "Johnny"] 
+1

Grazie, è interessante. Anche se dover usare 'String' per inizializzare una stringa è altrettanto inefficiente. : P In realtà preferirei usare 'rawValue' piuttosto che avvolgerlo in' String() '. – Joey

0

Se siete in grado di utilizzare User chiave come dizionario, invece di String (User è Hashable per impostazione predefinita) sarebbe una soluzione.

Se non si dovrebbe usare il proprio con una struttura nidificata e variabili/costanti statiche.

0

È possibile farlo con la classe personalizzata:

enum Names: String { 
    case something, thing 
} 

class CustomData { 
    subscript(key: Names) -> Any? { 
     get { 
      return self.customData[key.rawValue] 
     } 

     set(newValue) { 
      self.customData[key.rawValue] = newValue 
     } 
    } 

    private var customData = [String: Any]() 
} 

... 

let cData = CustomData() 
cData[Names.thing] = 56 

Edit:
ho trovato una un'altra soluzione, che il lavoro con Swift 3:

enum CustomKey: String { 
    case one, two, three 
} 

extension Dictionary where Key: ExpressibleByStringLiteral { 
    subscript(key: CustomKey) -> Value? { 
     get { 
      return self[key.rawValue as! Key] 
     } 
     set { 
      self[key.rawValue as! Key] = newValue 
     } 
    } 
} 

var dict: [String: Any] = [:] 
dict[CustomKey.one] = 1 
dict["two"] = true 
dict[.three] = 3 
print(dict["one"]!) 
print(dict[CustomKey.two]!) 
print(dict[.three]!) 
+0

Esiste comunque un modo per eseguire questa operazione per tutte le enumerazioni ereditate da una classe base? –

+0

Funziona solo per gli usi dell'enumerazione come chiave del dizionario? –

Problemi correlati