2014-12-30 23 views
9

Chcę powiązać dwie wartości surowców do wyliczenia instancji (wyobrazić enum reprezentujących typy błędów, chcę Error.Teapot mieć Typ własności Int code o wartości 418, a właściwości String ustawiony I'm a teapot).Czy wyliczenia Swift mają wiele wartości nieprzetworzonych?

Note różnica między raw values i associated values tutaj - chcę, aby wszystkie instancje Teapot miały wartość 418, nie chcę unikalnej wartości skojarzonej dla każdej instancji Teapot.

Czy istnieje lepszy sposób niż dodanie obliczonych właściwości do wyliczenia że switch ed na self zajrzeć do odpowiedniej wartości?

Odpowiedz

8

Nie, wyliczenie nie może mieć wielu wartości nieprzetworzonych - musi to być pojedyncza wartość, realizująca protokół Equatable i być dosłownie wymienialna, jak opisano w documentation.

Uważam, że najlepszym podejściem w twoim przypadku jest użycie kodu błędu jako wartości nieprzetworzonej oraz właściwości wspieranej przez wstępnie wypełniony słownik statyczny z kodem błędu jako kluczem i tekstem jako wartością.

2

Nie, nie można mieć wielu wartości nieprzetworzonych powiązanych z wyliczeniem.

W twoim przypadku możesz mieć wartość nieprzetworzoną równą kodowi i mieć powiązaną wartość z opisem. Ale myślę, że metoda obliczanych właściwości jest tutaj najlepszą opcją.

+0

podania wartości z opisu nie byłoby właściwe dla tego, co chcę. Wszystkie instancje 'Teapot' powinny mieć ten sam ciąg znaków; Chciałbym użyć powiązanej wartości typu String, jeśli chciałbym dołączyć say, notatkę na temat źródła określonej instancji błędu. –

1

Jednym z obejść, jeśli chcesz mieć wiele właściwości statycznych dla YourError może być zaimportowanie listy właściwości; możesz ustawić obiekt główny do słownika, z wartością surową wyliczenia jako kluczem dla każdego obiektu, umożliwiając łatwe pobieranie statycznych danych strukturalnych dla obiektu.

Ma przykład importowania i stosując plist: http://www.spritekitlessons.com/parsing-a-property-list-using-swift/

To może być przesadą prostu opisem usterki, na które można po prostu użyć Hardcoded funkcję statycznego z instrukcji switch dla wartości enum, że zwraca ciąg błędu, który potrzebujesz. Po prostu umieść funkcję statyczną w tym samym pliku .swift jako swoje wyliczenie.

Przykładowo

static func codeForError(error : YourErrorType) -> Int { 
    switch(error) { 
     case .Teapot: 
      return "I'm a Teapot" 
     case .Teacup: 
      return "I'm a Teacup" 
     ... 
     default: 
      return "Unknown Teaware Error" 
    } 
} 

ten ma tę zaletę, (w stosunku do roztworu) .plist lepszej przychylny lokalizacji. Jednak .plist może po prostu zawierać klucz służący do pobierania właściwej lokalizacji, zamiast ciągu błędów w tym celu.

0

Stworzyłem sposób na symulację tego (nie różni się od tego, co sugerował Marcos Crispino w swojej odpowiedzi). Daleko od idealnego rozwiązania, ale pozwala nam uniknąć tych nieprzyjemnych przypadków przełączania dla każdej innej właściwości, którą chcemy uzyskać.

Sztuką jest użycie struct jako właściciela "własności/danych" i użycie go jako wartości Raw w samym wyliczeniu.

Ma trochę duplikatów, ale dobrze mi to służy. Za każdym razem, gdy chcesz dodać nowy przypadek enum, kompilator przypomni ci, aby wypełnić dodatkowy przypadek w rawValue getter, co powinno przypomnieć o aktualizacji init?, która przypomina o utworzeniu nowej właściwości statycznej w strukturze.

Gist

Kod do Gist:

enum VehicleType : RawRepresentable { 

    struct Vehicle : Equatable { 
     let name: String 
     let wheels: Int 

     static func ==(l: Vehicle, r: Vehicle) -> Bool { 
      return l.name == r.name && l.wheels == r.wheels 
     } 

     static var bike: Vehicle { 
      return Vehicle(name: "Bicycle", wheels: 2) 
     } 

     static var car: Vehicle { 
      return Vehicle(name: "Automobile", wheels: 4) 
     } 

     static var bus: Vehicle { 
      return Vehicle(name: "Autobus", wheels: 8) 
     } 
    } 

    typealias RawValue = Vehicle 

    case car 
    case bus 
    case bike 

    var rawValue: RawValue { 
     switch self { 
     case .car: 
      return Vehicle.car 
     case .bike: 
      return Vehicle.bike 
     case .bus: 
      return Vehicle.bus 
     } 
    } 

    init?(rawValue: RawValue) { 
     switch rawValue { 
     case Vehicle.bike: 
      self = .bike 
     case Vehicle.car: 
      self = .car 
     case Vehicle.bus: 
      self = .bus 
     default: return nil 
     } 
    } 
} 

VehicleType.bike.rawValue.name 
VehicleType.bike.rawValue.wheels 
VehicleType.car.rawValue.wheels 

VehicleType(rawValue: .bike)?.rawValue.name => "Bicycle" 
VehicleType(rawValue: .bike)?.rawValue.wheels => 2 
VehicleType(rawValue: .car)?.rawValue.name => "Automobile" 
VehicleType(rawValue: .car)?.rawValue.wheels => 4 
VehicleType(rawValue: .bus)?.rawValue.name => "Autobus" 
VehicleType(rawValue: .bus)?.rawValue.wheels => 8