2014-06-05 10 views
22

Sto cercando di registrare un enum:Logging un enum Swift utilizzando NSLog

enum CKAccountStatus : Int { 
    case CouldNotDetermine 
    case Available 
    case Restricted 
    case NoAccount 
} 

NSLog("%i", CKAccountStatus.Available) 

Il compilatore si lamenta:

Type 'CKAccountStatus' does not conform to protocol 'CVarArg' 

Perché? Ho cercato di cast del valore:

NSLog("%i", CKAccountStatus.Available as Int) 

Ma che non vola neanche:

Cannot convert the expression's type '()' to type 'String' 
+0

hai provato 'println'? – Firo

+1

Sì, stampa '(Valore enumerato)'. Corretto, ma non molto utile :) – zoul

risposta

28

Diventa sottostante Int il valore della enum: CKAccountStatus.Available.rawValue.

Gli enumerati non sono strettamente interi in Swift, ma se sono dichiarati con un tipo sottostante è possibile ottenerlo con rawValue - qualunque sia il tipo sottostante. (enum Foo: String fornirà stringhe per lo rawValue, ecc.) Se un enum non ha un tipo sottostante, rawValue non ha nulla da darti. Nelle API importate da ObjC, qualsiasi enum definito con NS_ENUM ha un tipo intero sottostante (in genere Int).

Se si desidera stampare qualsiasi enumerazione in modo più descrittivo, è possibile prendere in considerazione la creazione di un'estensione del tipo enum che adotta il protocollo Printable.

+1

Ho trovato per semplice enumerazione 'Int',' .hashValue' fornirà anche l'accesso al valore 'Int'. – tfrank377

+2

L'uso di 'hashValue' sarebbe un abuso del contratto API. Un tipo 'Hashable' richiede che' hashValue' sia identico per i valori "uguale" e univoco altrimenti, ma non offre altre garanzie ... anche se per coincidenza restituisce lo stesso valore di 'rawValue' per un tipo di enum' Int', non si So che non cambierà in futuro. È sempre meglio scegliere l'API che è documentata per fare ciò che vuoi su quello che succede a fare quello che vuoi. – rickster

0

vedo, enumerazioni non sono numeri a Swift:

A differenza di C e Objective -C, ai membri di enumerazione Swift non viene assegnato un valore intero predefinito quando vengono creati. Nell'esempio CompassPoints sopra, Nord, Sud, Est e Ovest non sono uguali implicitamente 0, 1, 2 e 3. Invece, i diversi membri di enumerazione sono valori completi a pieno titolo, con un valore definito tipo di CompassPoint.

C'è un modo per registrare facilmente il valore, quindi? Ah, c'è:

NSLog("%i", CKAccountStatus.Available.toRaw()) 
1

Dalla documentazione Swift:

Se si ha familiarità con C, si sa che C enumerazioni assegnano nomi legati a un insieme di valori interi. Le enumerazioni in Swift sono molto più flessibili e non devono fornire un valore per ogni membro dell'enumerazione. Se un valore (noto come valore "raw") viene fornito per ciascun membro di enumerazione, il valore può essere una stringa, un carattere o un valore di qualsiasi numero intero o tipo a virgola mobile.

Quindi non si può provare a lanciarlo su e Int. Per quanto riguarda il tuo primo problema, sembra che NSLog() stia cercando un parametro di tipo C-variabile, che non si applica alle enumerazioni Swift.

0

È possibile utilizzare la funzione toRaw() per ottenere l'Int valore della enum come segue:

import Foundation 

enum CKAccountStatus : Int { 
    case CouldNotDetermine 
    case Available 
    case Restricted 
    case NoAccount 
} 

let block = {(status: Int) -> Void in 
    NSLog("%d", status) 
} 

let status = CKAccountStatus.Available.toRaw() 
block(status) // prints "1" 
+0

Come stampare "Disponibile"? – CZ54

7

un enum è effettivamente opaco. Potrebbe avere valori non elaborati, che puoi ottenere; ma molte enumerazioni no.(Non devi dichiarare l'enum come se avessi un tipo, e se non lo fai, non ci sono valori grezzi.) Quello che farei è dare all'enum un metodo description e chiamarlo esplicitamente.

L'unico modo per distinguere il valore corrente dell'enumerazione è tramite un'istruzione switch, quindi il tuo metodo description gestirà ciascun caso e ogni caso dell'istruzione switch restituirà un valore descrittivo diverso.

enum Suit { 
    case Hearts, Diamonds, Spades, Clubs 
    func description() -> String { 
     switch self { 
     case Hearts: 
      return "hearts" 
     case Diamonds: 
      return "diamonds" 
     case Spades: 
      return "spades" 
     case Clubs: 
      return "clubs" 
     } 
    } 
} 

var suit = Suit.Diamonds 
println("suit \(suit.description())") // suit diamonds 
5

Questo è il mio approccio:

enum UserMode : String 
{ 
    case Hold = "Hold"; 
    case Selecting = "Selecting"; 
    case Dragging = "Dragging"; 
} 

Poi, ogni volta che ho bisogno di stampare il valore grezzo:

//Assuming I have this declared and set somewhere 
var currentMode: UserMode = .Selecting; 

Facendo

NSLog("CurrentMode \(_currMode.rawValue)"); 

Stamperà:

CurrentMode Selezione