2014-06-05 14 views
22

Ich versuche, eine ENUM zu protokollieren:Logging ein Swift Enum mit NSLog

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

NSLog("%i", CKAccountStatus.Available) 

Der Compiler beschwert sich:

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

Warum? Ich habe versucht, den Wert zu werfen:

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

Aber das Fliegen auch nicht:

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

haben Sie 'println' versucht? – Firo

+1

Ich tat, es druckt '(Enum-Wert)'. Richtig, aber nicht sehr hilfreich :) – zoul

Antwort

28

ENUM zugrunde liegenden Int Wert Get: CKAccountStatus.Available.rawValue.

Aufzählungen sind in Swift keine genauen Ganzzahlen, aber wenn sie mit einem zugrunde liegenden Typ deklariert sind, können Sie sie mit rawValue bekommen - was auch immer dieser zugrunde liegende Typ ist. (enum Foo: String gibt Ihnen Strings für die rawValue, etc.) Wenn eine Enum keinen zugrunde liegenden Typ hat, hat rawValue nichts zu geben. In APIs, die aus ObjC importiert wurden, hat jede mit NS_ENUM definierte Enumeration einen zugrunde liegenden Integer-Typ (normalerweise Int).

Wenn Sie eine Enumeration deskriptiver drucken möchten, sollten Sie eine Erweiterung für den Enum-Typ erstellen, der das Printable-Protokoll annimmt.

+1

Ich habe für einfache 'Int' enums gefunden,' .hashValue' gibt Ihnen auch Zugriff auf den 'Int' Wert. – tfrank377

+2

Die Verwendung von 'hashValue' wäre ein Missbrauch des API-Vertrags. Ein 'Hashable'-Typ erfordert, dass' hashValue' identisch für "gleiche" Werte und eindeutig anders ist, aber keine anderen Garantien gibt ... selbst wenn es zufälligerweise denselben Wert wie 'rawValue' für einen' Int'-Enum-Typ zurückgibt Ich weiß nicht, dass sich das in Zukunft nicht ändern wird. Es ist immer am besten, die API zu wählen, die dokumentiert ist, um das zu tun, was Sie wollen, über das, das zufällig tut, was Sie wollen. – rickster

0

ich sehe, Aufzählungen sind nicht Zahlen in Swift:

Im Gegensatz zu C und Objective -C, Swift-Enumerationselemente werden beim Erstellen keinen Standard-Ganzzahlwert zugewiesen. In den oben genannten CompassPoints sind Norden, Süden, Osten und Westen nicht implizit gleich 0, 1, 2 und 3. Stattdessen sind die verschiedenen Aufzählungsmember vollwertige eigene Werte mit einem explizit definierten Art von CompassPoint.

Gibt es eine Möglichkeit, den Wert einfach zu protokollieren, dann? Ah, da ist:

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

Aus der Swift-Dokumentation:

Wenn Sie mit C vertraut sind, werden Sie wissen, dass C Aufzählungen auf einen Satz von ganzzahligen Werten im Zusammenhang Namen zuweisen. Aufzählungen in Swift sind viel flexibler und müssen keinen Wert für jedes Element der Aufzählung bereitstellen. Wenn für jedes Aufzählungselement ein Wert (ein sogenannter "roher" Wert) bereitgestellt wird, kann der Wert eine Zeichenfolge, ein Zeichen oder ein Wert eines beliebigen Ganzzahl- oder Gleitkommatyps sein.

Daher können Sie nicht versuchen, es zu Int zu werfen. Soweit Ihr erstes Problem scheint es, dass NSLog() nach einem Parameter des Typs C-Variable sucht, die nicht auf Swift enums gilt.

0

können Sie die toRaw() Funktion verwenden, um den Int-Wert der Enumeration zu erhalten wie folgt:

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

So drucken Sie "Verfügbar"? – CZ54

7

Ein ENUM ist wirkungsvoll undurchsichtig. Es könnte rohe Werte haben, die Sie bekommen können; aber viele enums nicht.(Sie müssen die Enumeration nicht als einen Typ deklarieren, und wenn Sie dies nicht tun, gibt es keine Rohwerte.) Was ich tun würde, geben Sie der Enum eine description Methode und rufen Sie sie explizit.

Der einzige Weg, die ENUM aktuellen Wert zu unterscheiden, ist durch eine switch-Anweisung, so dass Ihre description Methode jeden Fall behandeln wird, und jeder Fall der switch-Anweisung einen anderen beschreibenden Wert zurück.

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

Das ist mein Ansatz:

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

Dann, wenn ich den Rohwert drucken müssen:

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

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

Druckt tun:

CurrentMode Wählen Sie