Как получить строковое представление Swift enum по умолчанию для дальнейшей настройки

Начнем с перечисления в Swift:

      enum UnitCode:UInt {
    case Unknown = 0
    case Hz = 1
    case GPM = 2
    case M3_Hour = 3
    case mA = 4
    case PSI = 5
    case Bar = 6
}

Для большинства из них используется такое выражение:

      let text = "\(aUnitCode)"

даст хороший результат, так как напечатанная форма соответствует форме кода (например, .Hz == "Hz").

Но для M3_Hour, Я хотел бы напечатать это как m³/hr. Так что соответствовать CustomStringConvertable, верно? Я подумал, что следующее не сработает:

      extension UnitCode: CustomStringConvertible {
    var description:String {
        return self == .M3_Hour ? "m³/hr" : String(describing: self)
    }
}

Это не так. Бесконечная рекурсия. Так и думал. Но Swift меня часто удивляет (как в хорошем, так и в плохом).

Если бы перечисление было отношением супер / подтип, я бы назвал «супер» версию описания, чтобы получить отображение текста перечисления «по умолчанию». Но я не уверен, как получить «строковую привязку перечисления по умолчанию» в моей ложной ветке, чтобы я мог настроить его только для одного отдельного значения. Есть ли способ сделать это?

3 ответа

Я думаю, проблема в том, что вы используете String(describing:)в реализации CustomStringConvertible. Если мы проигнорируем CustomStringConvertible и просто напишем настраиваемое свойство, вы сможете делать такие вещи:

      enum UnitCode: UInt {
    case Unknown = 0
    case Hz = 1
    case GPM = 2
    case M3_Hour = 3
    case mA = 4
    case PSI = 5
    case Bar = 6
    var toString : String {
        return self == .M3_Hour ? "m³/hr" : "\(self)"
    }
}

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

Комментарии о стиле и приемах приветствуются. Ответ, который я искал, пришел с форумов Swift и был очень простым:

К сожалению, нет. Функция, которую вам нужно вызвать, является внутренней по отношению к стандартной библиотеке.

Итак, в основном, механизм, который выполняет резервное преобразование из перечислений в их строки в кодировке, когда вы не предоставляете свои собственные реализация недоступна.

(Что @matt также сказал в комментариях, и если бы он дал такой ответ, я бы добавил еще больше очков к его огромному избытку репутации)

У меня это работает, надеюсь, вы этого и ожидали.

      enum UnitCode: UInt {
    case Unknown = 0
    case Hz = 1
    case GPM = 2
    case M3_Hour = 3
    case mA = 4
    case PSI = 5
    case Bar = 6
}

let anUnit: UnitCode = .M3_Hour

extension UnitCode: CustomStringConvertible {
    var description: String {
        switch self {
        case .M3_Hour:
            return "m³/hr"
        default:
            return String(describing: self)
        }
    }
}

print(anUnit.self)
//m³/hr
Другие вопросы по тегам