zoul
zoul

Reputation: 104065

Logging a Swift enum using NSLog

I’m trying to log an enum:

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

NSLog("%i", CKAccountStatus.Available)

The compiler complains:

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

Why? I have tried to cast the value:

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

But that doesn’t fly either:

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

Upvotes: 23

Views: 17249

Answers (7)

JMiguel
JMiguel

Reputation: 1589

For my Error enums I use

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

for other enums there is the CustomStringConvertible protocol that can be used as

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

Upvotes: 0

matt
matt

Reputation: 534885

An enum is effectively opaque. It might have raw values, which you can get; but many enums don't. (You don't have to declare the enum as having a type, and if you don't, there are no raw values.) What I would do is give the enum a description method and call it explicitly.

The only way to distinguish the enum's current value is through a switch statement, so your description method will handle each case, and each case of the switch statement will return a different descriptive value.

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

Upvotes: 8

Chris Amelinckx
Chris Amelinckx

Reputation: 4482

This is my approach:

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

Then, whenever I need to print the raw value:

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

Doing

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

Will print:

CurrentMode Selecting

Upvotes: 5

rickster
rickster

Reputation: 126107

Get the enum's underlying Int value:CKAccountStatus.Available.rawValue.

Enums are not strictly integers in Swift, but if they're declared with an underlying type you can get it with rawValue — whatever that underlying type is. (enum Foo: String will give you strings for the rawValue, etc.) If an enum doesn't have an underlying type, rawValue has nothing to give you. In APIs imported from ObjC, any enum defined with NS_ENUM has an underlying integer type (typically Int).

If you'd like to print any enum more descriptively, you might consider making an extension on the enum type that adopts the Printable protocol.

Upvotes: 30

Dennis Zoma
Dennis Zoma

Reputation: 2641

You can use the toRaw() function to get the Int-Value of the enum like follows:

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"

Upvotes: 0

67cherries
67cherries

Reputation: 6951

From the Swift docs:

If you are familiar with C, you will know that C enumerations assign related names to a set of integer values. Enumerations in Swift are much more flexible, and do not have to provide a value for each member of the enumeration. If a value (known as a “raw” value) is provided for each enumeration member, the value can be a string, a character, or a value of any integer or floating-point type.

Therefore you cannot try to cast it to and Int. As far as your first problem it seems that NSLog() is looking for a parameter of type C-variable, which does not apply to Swift enums.

Upvotes: 1

zoul
zoul

Reputation: 104065

I see, enums are not numbers in Swift:

Unlike C and Objective-C, Swift enumeration members are not assigned a default integer value when they are created. In the CompassPoints example above, North, South, East and West do not implicitly equal 0, 1, 2 and 3. Instead, the different enumeration members are fully-fledged values in their own right, with an explicitly-defined type of CompassPoint.

Is there a way to easily log the value, then? Ah, there is:

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

Upvotes: 0

Related Questions