Как я могу сделать TextAlignment Codable в SwiftUI? - PullRequest
0 голосов
/ 25 февраля 2020

Я знаю, как использовать rawValue, чтобы пользовательские перечисления соответствовали протоколу Codable, но есть ли способ заставить работать встроенные собственные перечисления?

Я хочу иметь возможность хранить и извлекать TextAlignment значений без необходимости заново изобретать колесо и создавать какое-то специальное решение.

Я не могу найти ни одного примера!

1 Ответ

3 голосов
/ 25 февраля 2020

К сожалению, пока нет.

Возможно, вы можете преобразовать их в строки типа \(alignment), а затем восстановить, повторив через allCases и выбрать одну, но я не рекомендую этот подход, так как нет гарантировать, что имена не изменятся в будущем.

Что я бы порекомендовал - это реализовать пользовательское соответствие Codable с использованием switch...case, например:

extension TextAlignment: Codable {

    /// Adding constants to make it less error prone when refactoring
    private static var leadingIntRepresentation = -1
    private static var centerIntRepresentation = 0
    private static var trailingIntRepresentation = 1

    /// Adding a way to represent TextAlignment as Int value
    /// You may choose a different type if more appropriate
    /// for your coding practice
    private var intRepresentation: Int {
        switch self {
        case .leading: return TextAlignment.leadingIntRepresentation
        case .center: return TextAlignment.centerIntRepresentation
        case .trailing: return TextAlignment.trailingIntRepresentation
        }
    }

    /// Initializing TextAlignment using Int
    /// Making the method private as our intention is to only use it for coding
    private init(_ intRepresentation: Int) {
        switch intRepresentation {
        case TextAlignment.leadingIntRepresentation: self = .leading
        case TextAlignment.trailingIntRepresentation: self = .trailing
        default: self = .center
        }
    }

    /// Conforming to Encodable
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(intRepresentation)
    }

    /// Conforming to Decodable
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        self.init(try container.decode(Int.self))
    }

}

Этот метод довольно безопасно. Единственным недостатком является то, что мы могли бы получить значение, отличное от -1, 0 и 1. Мы будем рассматривать такой случай как center. Вы можете вместо этого выдать ошибку.

...