Регистрация перечисления Swift с использованием NSLog

Я пытаюсь зарегистрировать перечисление:

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

NSLog("%i", CKAccountStatus.Available)

Компилятор жалуется:

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

Почему? Я попытался указать значение:

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

Но и это не летает:

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

person zoul    schedule 05.06.2014    source источник
comment
ты пробовал println?   -  person Firo    schedule 05.06.2014
comment
Я сделал, он печатает (Enum Value). Правильно, но не очень полезно :)   -  person zoul    schedule 05.06.2014


Ответы (7)


Получите базовое значение Int перечисления: CKAccountStatus.Available.rawValue.

Перечисления не являются строго целыми числами в Swift, но если они объявлены с базовым типом, вы можете получить его с помощью rawValue — каким бы ни был этот базовый тип. (enum Foo: String даст вам строки для rawValue и т. д.) Если перечисление не имеет базового типа, rawValue ничего вам не даст. В API, импортированных из ObjC, любое перечисление, определенное с помощью NS_ENUM, имеет базовый целочисленный тип (обычно Int).

Если вы хотите напечатать какое-либо перечисление более описательно, вы можете подумать о расширении типа перечисления, которое использует протокол Printable.

person rickster    schedule 05.06.2014
comment
Я нашел для простых перечислений Int, .hashValue также даст вам доступ к значению Int. - person tfrank377; 05.11.2014
comment
Использование hashValue будет нарушением контракта API. Тип Hashable требует, чтобы hashValue был идентичен для равных значений и уникален в противном случае, но не дает никаких других гарантий... даже если он случайно возвращает то же самое, что и rawValue для типа перечисления Int, вы не знаете, что это не изменится в будущее. Всегда лучше выбирать задокументированный API, который делает то, что вы хотите, а не тот, который делает то, что вы хотите. - person rickster; 05.11.2014

Перечисление эффективно непрозрачно. У него могут быть необработанные значения, которые вы можете получить; но многие перечисления этого не делают. (Вам не нужно объявлять перечисление как имеющее тип, а если вы этого не сделаете, необработанных значений не будет.) Я бы дал перечислению метод description и вызвал его явно.

Единственный способ отличить текущее значение перечисления — использовать оператор switch, поэтому ваш метод description будет обрабатывать каждый случай, и каждый случай оператора switch будет возвращать другое описательное значение.

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
person matt    schedule 05.06.2014

Это мой подход:

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

Затем, когда мне нужно напечатать необработанное значение:

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

Делает

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

Будет печатать:

Выбор текущего режима

person Chris Amelinckx    schedule 01.03.2015

Из документов Swift:

Если вы знакомы с C, вы знаете, что перечисления C присваивают связанные имена набору целочисленных значений. Перечисления в Swift гораздо более гибкие и не должны предоставлять значение для каждого члена перечисления. Если значение (известное как «необработанное» значение) предоставлено для каждого члена перечисления, значение может быть строкой, символом или значением любого целочисленного типа или типа с плавающей запятой.

Поэтому вы не можете пытаться привести его к и Int. Что касается вашей первой проблемы, кажется, что NSLog() ищет параметр типа C-переменной, который не применяется к перечислениям Swift.

person 67cherries    schedule 05.06.2014

Я вижу, перечисления не являются числами в Swift:

В отличие от C и Objective-C, членам перечисления Swift не присваивается целочисленное значение по умолчанию при их создании. В приведенном выше примере с CompassPoints север, юг, восток и запад не равны неявно 0, 1, 2 и 3. Вместо этого различные элементы перечисления являются полноценными значениями сами по себе с явно определенным типом CompassPoint.

Тогда есть ли способ легко зарегистрировать значение? Ах, есть:

NSLog("%i", CKAccountStatus.Available.toRaw())
person zoul    schedule 05.06.2014

Вы можете использовать функцию toRaw() для получения Int-Value перечисления следующим образом:

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"
person zoma    schedule 05.06.2014
comment
Как распечатать Доступно? - person CZ54; 08.03.2017

Для моих перечислений ошибок я использую

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

для других перечислений есть протокол CustomStringConvertible, который можно использовать как

public var description : String { return String(reflecting: self) }
person JMiguel    schedule 01.12.2018