web-dev-qa-db-fra.com

Consignation d'une énumération Swift à l'aide de NSLog

J'essaie de me connecter à un enum:

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

NSLog("%i", CKAccountStatus.Available)

Le compilateur se plaint:

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

Pourquoi? J'ai essayé de lancer la valeur:

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

Mais ça ne vole pas non plus:

Cannot convert the expression's type '()' to type 'String'
22
zoul

Obtenez la valeur Int sous-jacente de l'énumération: CKAccountStatus.Available.rawValue.

Les énumérations ne sont pas strictement des entiers dans Swift, mais si elles sont déclarées avec un type sous-jacent, vous pouvez l'obtenir avec rawValue - quel que soit ce type sous-jacent. (enum Foo: String vous donnera des chaînes pour la rawValue, etc.) Si une énumération n'a pas de type sous-jacent, rawValue n'a rien à vous donner. Dans les API importées d'ObjC, toute énumération définie avec NS_ENUM a un type entier sous-jacent (généralement Int).

Si vous souhaitez imprimer une énumération de manière plus descriptive, vous pouvez envisager de créer une extension sur le type d’énum qui adopte le protocole Printable.

28
rickster

Une énumération est effectivement opaque. Il peut avoir des valeurs brutes, que vous pouvez obtenir; mais beaucoup d'énums ne le font pas. (Vous n'êtes pas obligé de déclarer l'énum comme ayant un type, et sinon, il n'y a pas de valeur brute.) Ce que je ferais, c'est de lui donner une méthode description et de l'appeler explicitement.

Le seul moyen de distinguer la valeur actuelle de l'énum est d'utiliser une instruction switch. Votre méthode description gérera chaque cas et chaque cas de l'instruction switch renverra une valeur descriptive différente.

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
7
matt

Ceci est mon approche:

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

Ensuite, chaque fois que je dois imprimer la valeur brute:

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

Faire

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

Imprimera:

CurrentMode Sélection

5
Chris Amelinckx

De la documentation Swift:

Si vous connaissez C, vous saurez que les énumérations C attribuent des noms associés à un ensemble de valeurs entières. Les énumérations dans Swift sont beaucoup plus flexibles et n'ont pas à fournir de valeur pour chaque membre de l'énumération. Si une valeur (appelée valeur «brute») est fournie pour chaque membre d'énumération, elle peut être une chaîne, un caractère ou une valeur de type entier ou virgule flottante.

Par conséquent, vous ne pouvez pas essayer de le lancer vers et Int. En ce qui concerne votre premier problème, il semble que NSLog() recherche un paramètre de type C-variable, qui ne s’applique pas à l’énumération Swift. 

1
67cherries

Pour mes énormes erreurs que j'utilise 

public var localizedDescription : String { return String(reflecting: self) }

pour les autres énumérations, le protocole CustomStringConvertible peut être utilisé comme

public var description : String { return String(reflecting: self) }
0
JMiguel

Je vois, les énumérations ne sont pas des nombres dans Swift:

Contrairement à C et à Objective-C, les membres de l'énumération Swift ne sont pas affectés d'un valeur entière par défaut lors de leur création. Dans les CompassPoints exemple ci-dessus, Nord, Sud, Est et Ouest ne sont pas implicitement égaux à 0, 1, 2 et 3. Au lieu de cela, les différents membres du recensement sont des valeurs à part entière proprement dites, avec un .__ explicitement défini. type de CompassPoint.

Y at-il un moyen de consigner facilement la valeur, alors? Ah, il y a:

NSLog("%i", CKAccountStatus.Available.toRaw())
0
zoul

Vous pouvez utiliser la fonction toRaw() pour obtenir la valeur int de l'énum comme suit:

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
wottpal