SWIFT - вложенные перечисления - PullRequest
0 голосов
/ 02 августа 2020

В настоящий момент я работаю с перечислениями, где мне нужны разные случаи перечисления в хранилище объектов, но я хочу избежать использования оператора switch в каждой реализации. В моем пользовательском объекте я сохраняю его тип из перечисления « CarModType », где я указал больше подтипов как « Engine, Interior, Exterior ... ». Таким образом, я могу сохранить в своем объекте, что текущий объект имеет тип « Interior.Seats », и мне не нужно работать с изменчивостью моего «типа», равной var type: PostProcessingFramework.CarModType?, чтобы хранить различные перечисления для CarModType. например, « Двигатель, Внешний вид, Интерьер ». Мои перечисления выглядят так:

public enum CarModType {
        case interior(Interior)
        case exterior(Exterior)
        case engine(Engine)
        case driveTrain(DriveTrain)
        case suspension(Suspension)
        case steering(Steering)
        case brakes(Brakes)
        case extra(Extra) 

    enum Interior: String,CaseIterable {
            
            case steering = "interior.steering"
            case seats = "interior.seats"
            case shiftSystem = "interior.shiftSystem"
            case pedals = "interior.pedals"
            case accessories = "interior.accessories"
            case centralUnit = "interior.centralUnit"
            case extra = "interior.extra"
            
            
            class stored {
                static let array:[PostProcessingFramework.CarModType.Interior] = [.accessories,.centralUnit,.extra,.pedals,.seats,.shiftSystem,.steering]
            }

            static func returnTitle(category: PostProcessingFramework.CarModType.Interior) -> String {
                switch category {
                case .steering:
                    return "Steering"
                case .seats:
                    return "Seats"
                case .shiftSystem:
                    return "Shift System"
                case .pedals:
                    return "Pedals"
                case .accessories:
                    return "Accessories"
                case .centralUnit:
                    return "Central Unit"
                case .extra:
                    return "Extra"
                }
            }
        }

Затем я столкнулся с другой проблемой, из-за моей БД я сохраняю этот тип в его rawValue, как я указал в подтипах. Из-за этого я придумал несколько функций, которые преобразуют все случаи перечисления в словарь, а затем я могу получить доступ к этому словарю с ключом как rawValue вложенного Enum (subType), чтобы получить спецификацию c " Тип"(например, CarModType.Engine (.cylinderHead)) из rawValue. Мои функции:

static func returnType(rawValue: String) -> CarModType? {
     let semaphore = DispatchSemaphore(value: 0)
     let dictionaries = [
         Dictionary(uniqueKeysWithValues: CarModType.Interior.allCases.map{ (CarModType.interior($0).stringValue,CarModType.interior($0)) }),
         Dictionary(uniqueKeysWithValues: CarModType.Exterior.allCases.map{ (CarModType.exterior($0).stringValue,CarModType.exterior($0)) }),
         Dictionary(uniqueKeysWithValues: CarModType.Engine.allCases.map{ (CarModType.engine($0).stringValue,CarModType.engine($0)) })
     ]
     var dict = [String:CarModType]()
     var i = 0
     for subDict in dictionaries {
         dict.merge(subDict){(_, curr) in curr }
         i += 1
         if i == dictionaries.count {
             semaphore.signal()
         }
     }
     semaphore.wait()
     if let val = dict[rawValue] {
         return val
     } else {
        return nil
     }
 }

 var stringValue: String {
     switch self {
         
     case let .interior(subtype):
         if let type = PostProcessingFramework.CarModType.Interior.init(rawValue: subtype.rawValue) {
             return type.rawValue
         } else {
             return ""
         }
     case let .exterior(subtype):
         if let type = PostProcessingFramework.CarModType.Exterior.init(rawValue: subtype.rawValue) {
             return type.rawValue
         } else {
             return ""
         }
      case let .engine(subtype):
         if let type = PostProcessingFramework.CarModType.Engine.init(rawValue: subtype.rawValue) {
             return type.rawValue
         } else {
             return ""
         }
    }
}

Нет ли лучшего, более «элегантного» способа сделать это? Большое спасибо за ответы!

1 Ответ

0 голосов
/ 02 августа 2020

Предполагая, что все необработанные значения уникальны, как будто они предназначены для Interior с пространством имен, таким как строка, вы можете добавить init на верхнем уровне, который проходит и пытается создать экземпляр каждого подтипа до тех пор, пока успешно

Вот пример для двух первых элементов case

init?(asRaw: String) {
    if let item = Interior(rawValue: asRaw) {
        self = CarModType.interior(item)
    } else if let item = Exterior(rawValue: asRaw) {
        self = CarModType.exterior(item)
    //... rest of case items here
    } else {
        return nil
    }
}
...